Remove Murano

This removes all of the Murano code that is
deprecated in the 3.0.0 release.

When rally pulls in Murano it also pulls python-muranoclient
that depends on murano-pkg-check that is old code that
was also shown to fail the new setuptools version [1]
that removed support for dashes in setup.cfg that has
been deprecated since 2021.

[1] https://github.com/pypa/setuptools/issues/4910

Change-Id: Icb69c77f96fbf10be0def5be9e21c9af8f57761b
This commit is contained in:
Tobias Urdin 2025-03-25 09:14:16 +01:00
parent 582e8c0671
commit 109bf1e559
51 changed files with 9 additions and 2129 deletions

View File

@ -16,6 +16,14 @@ Changelog
.. Release notes for existing releases are MUTABLE! If there is something that
was missed or can be improved, feel free to change it!
Unreleased
----------
Removed
~~~~~~~
* Removed all support for the retired Murano project
[3.0.0] - 2024-05-23
--------------------

View File

@ -487,14 +487,6 @@
# (floating point value)
#monasca_metric_create_prepoll_delay = 15.0
# A timeout in seconds for an environment deploy (integer value)
# Deprecated group/name - [benchmark]/deploy_environment_timeout
#murano_deploy_environment_timeout = 1200
# Deploy environment check interval in seconds (integer value)
# Deprecated group/name - [benchmark]/deploy_environment_check_interval
#murano_deploy_environment_check_interval = 5
# Time to sleep after start before polling for status (floating point
# value)
#nova_server_start_prepoll_delay = 0.0

View File

@ -3,9 +3,3 @@ Extra files
All files from this directory will be copy pasted to gates, so you are able to
use absolute path in rally tasks. Files will be in ~/.rally/extra/*
murano/ directory
-----------------
Here we have Murano applications that is used to prepare Murano context and
to deploy environment.

View File

@ -1,25 +0,0 @@
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)

View File

@ -1,23 +0,0 @@
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']}

View File

@ -1,10 +0,0 @@
Format: 1.0
Type: Application
FullName: io.murano.apps.HelloReporter
Name: HelloReporter
Description: |
HelloReporter test app.
Author: 'Mirantis, Inc'
Tags: []
Classes:
io.murano.apps.HelloReporter: HelloReporter.yaml

View File

@ -1,17 +0,0 @@
Murano applications
===================
Files for Murano plugins
Structure
---------
* <application_name>/ directories. Each directory store a simple Murano package
for environment deployment in Murano context. Also there can be other files
needs for application.
Useful links
------------
* `More about Murano package <https://wiki.openstack.org/wiki/Murano/Documentation/How_to_create_application_package>`_

View File

@ -1,146 +0,0 @@
---
MuranoEnvironments.list_environments:
-
runner:
type: "constant"
times: 30
concurrency: 4
context:
users:
tenants: 2
users_per_tenant: 2
murano_environments:
environments_per_tenant: 2
sla:
failure_rate:
max: 0
MuranoEnvironments.create_and_delete_environment:
-
runner:
type: "constant"
times: 20
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 2
sla:
failure_rate:
max: 0
MuranoEnvironments.create_and_deploy_environment:
-
args:
packages_per_env: 2
runner:
type: "constant"
times: 8
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 2
murano_packages:
app_package: "~/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter.zip"
roles:
- "admin"
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: "~/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
roles:
- "admin"
MuranoPackages.import_and_list_packages:
-
args:
package: "~/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
runner:
type: "constant"
times: 10
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 2
sla:
failure_rate:
max: 0
-
args:
package: "~/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter.zip"
runner:
type: "constant"
times: 1
concurrency: 1
context:
users:
tenants: 1
users_per_tenant: 1
sla:
failure_rate:
max: 0
MuranoPackages.import_and_delete_package:
-
args:
package: "~/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
runner:
type: "constant"
times: 10
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 2
sla:
failure_rate:
max: 0
MuranoPackages.import_and_filter_applications:
-
args:
package: "~/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
filter_query: {"category" : "Web"}
runner:
type: "constant"
times: 10
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 2
sla:
failure_rate:
max: 0
MuranoPackages.package_lifecycle:
-
args:
package: "~/.rally/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
body: {"categories": ["Web"]}
operation: "add"
runner:
type: "constant"
times: 10
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 2
sla:
failure_rate:
max: 0

View File

@ -1,29 +0,0 @@
# Copyright 2013: Mirantis Inc.
# All Rights Reserved.
#
# 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 rally.common import cfg
OPTS = {"openstack": [
cfg.IntOpt("murano_deploy_environment_timeout",
default=1200,
deprecated_name="deploy_environment_timeout",
deprecated_group="benchmark",
help="A timeout in seconds for an environment deploy"),
cfg.IntOpt("murano_deploy_environment_check_interval",
default=5,
deprecated_name="deploy_environment_check_interval",
deprecated_group="benchmark",
help="Deploy environment check interval in seconds"),
]}

View File

@ -21,7 +21,6 @@ from rally_openstack.common.cfg import magnum
from rally_openstack.common.cfg import manila
from rally_openstack.common.cfg import mistral
from rally_openstack.common.cfg import monasca
from rally_openstack.common.cfg import murano
from rally_openstack.common.cfg import neutron
from rally_openstack.common.cfg import nova
from rally_openstack.common.cfg import octavia
@ -46,7 +45,7 @@ def list_opts():
opts = {}
for l_opts in (cinder.OPTS, heat.OPTS, ironic.OPTS, magnum.OPTS,
manila.OPTS, mistral.OPTS, monasca.OPTS, murano.OPTS,
manila.OPTS, mistral.OPTS, monasca.OPTS,
nova.OPTS, osclients.OPTS, profiler.OPTS, sahara.OPTS,
vm.OPTS, glance.OPTS, watcher.OPTS, tempest.OPTS,
keystone_roles.OPTS, keystone_users.OPTS, cleanup.OPTS,

View File

@ -62,7 +62,6 @@ class _Service(utils.ImmutableMixin, utils.EnumMixin):
SAHARA = "sahara"
SWIFT = "swift"
MISTRAL = "mistral"
MURANO = "murano"
IRONIC = "ironic"
GNOCCHI = "gnocchi"
MAGNUM = "magnum"
@ -96,7 +95,6 @@ class _ServiceType(utils.ImmutableMixin, utils.EnumMixin):
DATA_PROCESSING_MOS = "data_processing"
OBJECT_STORE = "object-store"
WORKFLOW_EXECUTION = "workflowv2"
APPLICATION_CATALOG = "application-catalog"
BARE_METAL = "baremetal"
METRIC = "metric"
CONTAINER_INFRA = "container-infra"
@ -130,7 +128,6 @@ class _ServiceType(utils.ImmutableMixin, utils.EnumMixin):
self.DATA_PROCESSING_MOS: _Service.SAHARA,
self.OBJECT_STORE: _Service.SWIFT,
self.WORKFLOW_EXECUTION: _Service.MISTRAL,
self.APPLICATION_CATALOG: _Service.MURANO,
self.BARE_METAL: _Service.IRONIC,
self.METRIC: _Service.GNOCCHI,
self.CONTAINER_INFRA: _Service.MAGNUM,

View File

@ -660,25 +660,6 @@ class Zaqar(OSClient):
return client
@configure("murano", default_version="1",
default_service_type="application-catalog",
supported_versions=["1"])
class Murano(OSClient):
"""Wrapper for MuranoClient which returns an authenticated native client.
"""
def create_client(self, version=None, service_type=None):
"""Return Murano client."""
from muranoclient import client as murano
client = murano.Client(self.choose_version(version),
endpoint=self._get_endpoint(service_type),
token=self.keystone.auth_ref.auth_token)
return client
@configure("designate", default_version="2", default_service_type="dns",
supported_versions=["2"])
class Designate(OSClient):

View File

@ -872,25 +872,6 @@ class MistralExecutions(SynchronizedDeletion, base.ResourceManager):
# after workflow deletion.
return self.raw_resource.workflow_name
# MURANO
_murano_order = get_order(1200)
@base.resource("murano", "environments", tenant_resource=True,
order=next(_murano_order))
class MuranoEnvironments(SynchronizedDeletion, base.ResourceManager):
pass
@base.resource("murano", "packages", tenant_resource=True,
order=next(_murano_order))
class MuranoPackages(base.ResourceManager):
def list(self):
return filter(lambda x: x.name != "Core library",
super(MuranoPackages, self).list())
# IRONIC

View File

@ -1,58 +0,0 @@
# Copyright 2016: Mirantis Inc.
# All Rights Reserved.
#
# 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 rally.common import validation
from rally_openstack.common import consts
from rally_openstack.task.cleanup import manager as resource_manager
from rally_openstack.task import context
from rally_openstack.task.scenarios.murano import utils as murano_utils
@validation.add("required_platform", platform="openstack", users=True)
@context.configure(name="murano_environments", platform="openstack", order=402)
class EnvironmentGenerator(context.OpenStackContext):
"""Context class for creating murano environments."""
CONFIG_SCHEMA = {
"type": "object",
"$schema": consts.JSON_SCHEMA,
"properties": {
"environments_per_tenant": {
"type": "integer",
"minimum": 1
},
},
"required": ["environments_per_tenant"],
"additionalProperties": False
}
def setup(self):
for user, tenant_id in self._iterate_per_tenants():
self.context["tenants"][tenant_id]["environments"] = []
for i in range(self.config["environments_per_tenant"]):
murano_util = murano_utils.MuranoScenario(
{"user": user,
"task": self.context["task"],
"owner_id": self.context["owner_id"],
"config": self.context["config"]})
env = murano_util._create_environment()
self.context["tenants"][tenant_id]["environments"].append(env)
def cleanup(self):
resource_manager.cleanup(names=["murano.environments"],
users=self.context.get("users", []),
superclass=murano_utils.MuranoScenario,
task_id=self.get_owner_id())

View File

@ -1,78 +0,0 @@
# Copyright 2015: Mirantis Inc.
# All Rights Reserved.
#
# 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 io
import os
import zipfile
from rally.common import validation
from rally import exceptions
from rally_openstack.common import consts
from rally_openstack.common import osclients
from rally_openstack.task.cleanup import manager as resource_manager
from rally_openstack.task import context
from rally_openstack.task.scenarios.murano import utils as mutils
@validation.add("required_platform", platform="openstack", users=True)
@context.configure(name="murano_packages", platform="openstack", order=401)
class PackageGenerator(context.OpenStackContext):
"""Context class for uploading applications for murano."""
CONFIG_SCHEMA = {
"type": "object",
"$schema": consts.JSON_SCHEMA,
"properties": {
"app_package": {
"type": "string",
}
},
"required": ["app_package"],
"additionalProperties": False
}
def setup(self):
is_config_app_dir = False
pckg_path = os.path.expanduser(self.config["app_package"])
if zipfile.is_zipfile(pckg_path):
zip_name = pckg_path
elif os.path.isdir(pckg_path):
is_config_app_dir = True
zip_name = mutils.pack_dir(pckg_path)
else:
msg = "There is no zip archive or directory by this path: %s"
raise exceptions.ContextSetupFailure(msg=msg % pckg_path,
ctx_name=self.get_name())
for user, tenant_id in self._iterate_per_tenants():
clients = osclients.Clients(user["credential"])
self.context["tenants"][tenant_id]["packages"] = []
if is_config_app_dir:
self.context["tenants"][tenant_id]["murano_ctx"] = zip_name
# TODO(astudenov): use self.generate_random_name()
with open(zip_name, "rb") as f:
file = io.BytesIO(f.read())
package = clients.murano().packages.create(
{"categories": ["Web"], "tags": ["tag"]},
{"file": file})
self.context["tenants"][tenant_id]["packages"].append(package)
def cleanup(self):
resource_manager.cleanup(names=["murano.packages"],
users=self.context.get("users", []),
superclass=self.__class__,
task_id=self.get_owner_id())

View File

@ -1,77 +0,0 @@
# Copyright 2015: Mirantis Inc.
# All Rights Reserved.
#
# 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 rally.task import validation
from rally_openstack.common import consts
from rally_openstack.task import scenario
from rally_openstack.task.scenarios.murano import utils
"""Scenarios for Murano environments."""
@validation.add("required_services", services=[consts.Service.MURANO])
@scenario.configure(name="MuranoEnvironments.list_environments",
platform="openstack")
class ListEnvironments(utils.MuranoScenario):
def run(self):
"""List the murano environments.
Run murano environment-list for listing all environments.
"""
self._list_environments()
@validation.add("required_services", services=[consts.Service.MURANO])
@scenario.configure(context={"cleanup@openstack": ["murano.environments"]},
name="MuranoEnvironments.create_and_delete_environment",
platform="openstack")
class CreateAndDeleteEnvironment(utils.MuranoScenario):
def run(self):
"""Create environment, session and delete environment."""
environment = self._create_environment()
self._create_session(environment.id)
self._delete_environment(environment)
@validation.add("required_services", services=[consts.Service.MURANO])
@validation.add("required_contexts", contexts=("murano_packages"))
@scenario.configure(context={"cleanup@openstack": ["murano"],
"roles@openstack": ["admin"]},
name="MuranoEnvironments.create_and_deploy_environment",
platform="openstack")
class CreateAndDeployEnvironment(utils.MuranoScenario):
def run(self, packages_per_env=1):
"""Create environment, session and deploy environment.
Create environment, create session, add app to environment
packages_per_env times, send environment to deploy.
:param packages_per_env: number of packages per environment
"""
environment = self._create_environment()
session = self._create_session(environment.id)
package = self.context["tenant"]["packages"][0]
for i in range(packages_per_env):
self._create_service(environment, session,
package.fully_qualified_name)
self._deploy_environment(environment, session)

View File

@ -1,159 +0,0 @@
# Copyright 2015: Mirantis Inc.
# All Rights Reserved.
#
# 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 rally.task import types
from rally.task import validation
from rally_openstack.common import consts
from rally_openstack.task import scenario
from rally_openstack.task.scenarios.murano import utils
"""Scenarios for Murano packages."""
@types.convert(package={"type": "expand_user_path"})
@validation.add("file_exists", param_name="package", mode=os.F_OK)
@validation.add("required_services", services=[consts.Service.MURANO])
@validation.add("required_platform", platform="openstack", users=True)
@scenario.configure(context={"cleanup@openstack": ["murano.packages"]},
name="MuranoPackages.import_and_list_packages",
platform="openstack")
class ImportAndListPackages(utils.MuranoScenario):
def run(self, package, include_disabled=False):
"""Import Murano package and get list of packages.
Measure the "murano import-package" and "murano package-list" commands
performance.
It imports Murano package from "package" (if it is not a zip archive
then zip archive will be prepared) and gets list of imported packages.
:param package: path to zip archive that represents Murano
application package or absolute path to folder with
package components
:param include_disabled: specifies whether the disabled packages will
be included in a the result or not.
Default value is False.
"""
package_path = self._zip_package(package)
try:
self._import_package(package_path)
self._list_packages(include_disabled=include_disabled)
finally:
os.remove(package_path)
@types.convert(package={"type": "expand_user_path"})
@validation.add("file_exists", param_name="package", mode=os.F_OK)
@validation.add("required_services", services=[consts.Service.MURANO])
@validation.add("required_platform", platform="openstack", users=True)
@scenario.configure(context={"cleanup@openstack": ["murano.packages"]},
name="MuranoPackages.import_and_delete_package",
platform="openstack")
class ImportAndDeletePackage(utils.MuranoScenario):
def run(self, package):
"""Import Murano package and then delete it.
Measure the "murano import-package" and "murano package-delete"
commands performance.
It imports Murano package from "package" (if it is not a zip archive
then zip archive will be prepared) and deletes it.
:param package: path to zip archive that represents Murano
application package or absolute path to folder with
package components
"""
package_path = self._zip_package(package)
try:
package = self._import_package(package_path)
self._delete_package(package)
finally:
os.remove(package_path)
@types.convert(package={"type": "expand_user_path"})
@validation.add("file_exists", param_name="package", mode=os.F_OK)
@validation.add("required_services", services=[consts.Service.MURANO])
@validation.add("required_platform", platform="openstack", users=True)
@scenario.configure(context={"cleanup@openstack": ["murano.packages"]},
name="MuranoPackages.package_lifecycle",
platform="openstack")
class PackageLifecycle(utils.MuranoScenario):
def run(self, package, body, operation="replace"):
"""Import Murano package, modify it and then delete it.
Measure the Murano import, update and delete package
commands performance.
It imports Murano package from "package" (if it is not a zip archive
then zip archive will be prepared), modifies it (using data from
"body") and deletes.
:param package: path to zip archive that represents Murano
application package or absolute path to folder with
package components
:param body: dict object that defines what package property will be
updated, e.g {"tags": ["tag"]} or {"enabled": "true"}
:param operation: string object that defines the way of how package
property will be updated, allowed operations are
"add", "replace" or "delete".
Default value is "replace".
"""
package_path = self._zip_package(package)
try:
package = self._import_package(package_path)
self._update_package(package, body, operation)
self._delete_package(package)
finally:
os.remove(package_path)
@types.convert(package={"type": "expand_user_path"})
@validation.add("file_exists", param_name="package", mode=os.F_OK)
@validation.add("required_services", services=[consts.Service.MURANO])
@validation.add("required_platform", platform="openstack", users=True)
@scenario.configure(context={"cleanup@openstack": ["murano.packages"]},
name="MuranoPackages.import_and_filter_applications",
platform="openstack")
class ImportAndFilterApplications(utils.MuranoScenario):
def run(self, package, filter_query):
"""Import Murano package and then filter packages by some criteria.
Measure the performance of package import and package
filtering commands.
It imports Murano package from "package" (if it is not a zip archive
then zip archive will be prepared) and filters packages by some
criteria.
:param package: path to zip archive that represents Murano
application package or absolute path to folder with
package components
:param filter_query: dict that contains filter criteria, lately it
will be passed as **kwargs to filter method
e.g. {"category": "Web"}
"""
package_path = self._zip_package(package)
try:
self._import_package(package_path)
self._filter_applications(filter_query)
finally:
os.remove(package_path)

View File

@ -1,291 +0,0 @@
# Copyright 2015: Mirantis Inc.
# All Rights Reserved.
#
# 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
import shutil
import tempfile
import uuid
import zipfile
from rally.common import cfg
from rally.common import utils as common_utils
from rally.task import atomic
from rally.task import utils
import yaml
from rally_openstack.task import scenario
CONF = cfg.CONF
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 are 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
class MuranoScenario(scenario.OpenStackScenario):
"""Base class for Murano scenarios with basic atomic actions."""
@atomic.action_timer("murano.list_environments")
def _list_environments(self):
"""Return environments list."""
return self.clients("murano").environments.list()
@atomic.action_timer("murano.create_environment")
def _create_environment(self):
"""Create environment.
:param env_name: String used to name environment
:returns: Environment instance
"""
env_name = self.generate_random_name()
return self.clients("murano").environments.create({"name": env_name})
@atomic.action_timer("murano.delete_environment")
def _delete_environment(self, environment):
"""Delete given environment.
Return when the environment is actually deleted.
:param environment: Environment instance
"""
self.clients("murano").environments.delete(environment.id)
@atomic.action_timer("murano.create_session")
def _create_session(self, environment_id):
"""Create session for environment with specific id
:param environment_id: Environment id
:returns: Session instance
"""
return self.clients("murano").sessions.configure(environment_id)
@atomic.action_timer("murano.create_service")
def _create_service(self, environment, session, full_package_name,
image_name=None, flavor_name=None):
"""Create Murano service.
:param environment: Environment instance
:param session: Session instance
:param full_package_name: full name of the Murano package
:param image_name: Image name
:param flavor_name: Flavor name
:returns: Service instance
"""
app_id = str(uuid.uuid4())
data = {"?": {"id": app_id,
"type": full_package_name},
"name": self.generate_random_name()}
return self.clients("murano").services.post(
environment_id=environment.id, path="/", data=data,
session_id=session.id)
@atomic.action_timer("murano.deploy_environment")
def _deploy_environment(self, environment, session):
"""Deploy environment.
:param environment: Environment instance
:param session: Session instance
"""
self.clients("murano").sessions.deploy(environment.id,
session.id)
config = CONF.openstack
utils.wait_for_status(
environment,
ready_statuses=["READY"],
update_resource=utils.get_from_manager(["DEPLOY FAILURE"]),
timeout=config.murano_deploy_environment_timeout,
check_interval=config.murano_deploy_environment_check_interval
)
@atomic.action_timer("murano.list_packages")
def _list_packages(self, include_disabled=False):
"""Returns packages list.
:param include_disabled: if "True" then disabled packages will be
included in a the result.
Default value is False.
:returns: list of imported packages
"""
return self.clients("murano").packages.list(
include_disabled=include_disabled)
@atomic.action_timer("murano.import_package")
def _import_package(self, package):
"""Import package to the Murano.
:param package: path to zip archive with Murano application
:returns: imported package
"""
package = self.clients("murano").packages.create(
{}, {"file": open(package)}
)
return package
@atomic.action_timer("murano.delete_package")
def _delete_package(self, package):
"""Delete specified package.
:param package: package that will be deleted
"""
self.clients("murano").packages.delete(package.id)
@atomic.action_timer("murano.update_package")
def _update_package(self, package, body, operation="replace"):
"""Update specified package.
:param package: package that will be updated
:param body: dict object that defines what package property will be
updated, e.g {"tags": ["tag"]} or {"enabled": "true"}
:param operation: string object that defines the way of how package
property will be updated, allowed operations are
"add", "replace" or "delete".
Default value is "replace".
:returns: updated package
"""
return self.clients("murano").packages.update(
package.id, body, operation)
@atomic.action_timer("murano.filter_applications")
def _filter_applications(self, filter_query):
"""Filter list of uploaded application by specified criteria.
:param filter_query: dict that contains filter criteria, it
will be passed as **kwargs to filter method
e.g. {"category": "Web"}
:returns: filtered list of packages
"""
return self.clients("murano").packages.filter(**filter_query)
def _zip_package(self, package_path):
"""Call _prepare_package method that returns path to zip archive."""
return MuranoPackageManager(self.task)._prepare_package(package_path)
class MuranoPackageManager(common_utils.RandomNameGeneratorMixin):
RESOURCE_NAME_FORMAT = "app.rally_XXXXXXXX_XXXXXXXX"
def __init__(self, task):
self.task = task
@staticmethod
def _read_from_file(filename):
with open(filename, "r") as f:
read_data = f.read()
return yaml.safe_load(read_data)
@staticmethod
def _write_to_file(data, filename):
with open(filename, "w") as f:
yaml.safe_dump(data, f)
def _change_app_fullname(self, app_dir):
"""Change application full name.
To avoid name conflict error during package import (when user
tries to import a few packages into the same tenant) need to change the
application name. For doing this need to replace following parts
in manifest.yaml
from
...
FullName: app.name
...
Classes:
app.name: app_class.yaml
to:
...
FullName: <new_name>
...
Classes:
<new_name>: app_class.yaml
:param app_dir: path to directory with Murano application context
"""
new_fullname = self.generate_random_name()
manifest_file = os.path.join(app_dir, "manifest.yaml")
manifest = self._read_from_file(manifest_file)
class_file_name = manifest["Classes"][manifest["FullName"]]
# update manifest.yaml file
del manifest["Classes"][manifest["FullName"]]
manifest["FullName"] = new_fullname
manifest["Classes"][new_fullname] = class_file_name
self._write_to_file(manifest, manifest_file)
def _prepare_package(self, package_path):
"""Check whether the package path is path to zip archive or not.
If package_path is not a path to zip archive but path to Murano
application folder, than method prepares zip archive with Murano
application. It copies directory with Murano app files to temporary
folder, changes manifest.yaml and class file (to avoid '409 Conflict'
errors in Murano) and prepares zip package.
:param package_path: path to zip archive or directory with package
components
:returns: path to zip archive with Murano application
"""
if not zipfile.is_zipfile(package_path):
tmp_dir = tempfile.mkdtemp()
pkg_dir = os.path.join(tmp_dir, "package/")
try:
shutil.copytree(os.path.expanduser(package_path), pkg_dir)
self._change_app_fullname(pkg_dir)
package_path = pack_dir(pkg_dir)
finally:
shutil.rmtree(tmp_dir)
return package_path

View File

@ -21,7 +21,6 @@ python-keystoneclient!=2.1.0 # Apache Software License
python-magnumclient # Apache Software License
python-manilaclient # Apache Software License
python-mistralclient!=3.2.0 # Apache Software License
python-muranoclient # Apache License, Version 2.0
python-monascaclient # Apache Software License
python-neutronclient # Apache Software License
python-novaclient # Apache License, Version 2.0

View File

@ -1,23 +0,0 @@
{
"Dummy.openstack": [
{
"args": {
"sleep": 0.1
},
"runner": {
"type": "constant",
"times": 4,
"concurrency": 2
},
"context": {
"users": {
"tenants": 2,
"users_per_tenant": 2
},
"murano_environments": {
"environments_per_tenant": 2
}
}
}
]
}

View File

@ -1,15 +0,0 @@
---
Dummy.openstack:
-
args:
sleep: 0.1
runner:
type: "constant"
times: 4
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 2
murano_environments:
environments_per_tenant: 2

View File

@ -1,44 +0,0 @@
{
"Dummy.openstack": [
{
"args": {
"sleep": 0.1
},
"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.zip"
},
"roles": ["admin"]
}
},
{
"args": {
"sleep": 0.1
},
"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"]
}
}
]
}

View File

@ -1,32 +0,0 @@
---
Dummy.openstack:
-
args:
sleep: 0.1
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.zip"
roles:
- "admin"
-
args:
sleep: 0.1
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"

View File

@ -1,22 +0,0 @@
{
"MuranoEnvironments.create_and_delete_environment": [
{
"runner": {
"type": "constant",
"times": 10,
"concurrency": 2
},
"context": {
"users": {
"tenants": 2,
"users_per_tenant": 2
}
},
"sla": {
"failure_rate": {
"max": 0
}
}
}
]
}

View File

@ -1,14 +0,0 @@
---
MuranoEnvironments.create_and_delete_environment:
-
runner:
type: "constant"
times: 10
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 2
sla:
failure_rate:
max: 0

View File

@ -1,54 +0,0 @@
{
"MuranoEnvironments.create_and_deploy_environment": [
{
"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.zip"
},
"roles": ["admin"]
},
"sla": {
"failure_rate": {
"max": 0
}
}
},
{
"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"]
},
"sla": {
"failure_rate": {
"max": 0
}
}
}
]
}

View File

@ -1,38 +0,0 @@
---
MuranoEnvironments.create_and_deploy_environment:
-
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.zip"
roles:
- "admin"
sla:
failure_rate:
max: 0
-
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"
sla:
failure_rate:
max: 0

View File

@ -1,25 +0,0 @@
{
"MuranoPackages.import_and_delete_package": [
{
"args": {
"package": "rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
},
"runner": {
"type": "constant",
"times": 5,
"concurrency": 2
},
"context": {
"users": {
"tenants": 2,
"users_per_tenant": 1
}
},
"sla": {
"failure_rate": {
"max": 0
}
}
}
]
}

View File

@ -1,16 +0,0 @@
---
MuranoPackages.import_and_delete_package:
-
args:
package: "rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
runner:
type: "constant"
times: 5
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 1
sla:
failure_rate:
max: 0

View File

@ -1,26 +0,0 @@
{
"MuranoPackages.import_and_filter_applications": [
{
"args": {
"package": "rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/",
"filter_query": {"category" : "Web"}
},
"runner": {
"type": "constant",
"times": 5,
"concurrency": 2
},
"context": {
"users": {
"tenants": 2,
"users_per_tenant": 1
}
},
"sla": {
"failure_rate": {
"max": 0
}
}
}
]
}

View File

@ -1,17 +0,0 @@
---
MuranoPackages.import_and_filter_applications:
-
args:
package: "rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
filter_query: {"category" : "Web"}
runner:
type: "constant"
times: 5
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 1
sla:
failure_rate:
max: 0

View File

@ -1,25 +0,0 @@
{
"MuranoPackages.import_and_list_packages": [
{
"args": {
"package": "rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
},
"runner": {
"type": "constant",
"times": 5,
"concurrency": 2
},
"context": {
"users": {
"tenants": 2,
"users_per_tenant": 1
}
},
"sla": {
"failure_rate": {
"max": 0
}
}
}
]
}

View File

@ -1,16 +0,0 @@
---
MuranoPackages.import_and_list_packages:
-
args:
package: "rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
runner:
type: "constant"
times: 5
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 1
sla:
failure_rate:
max: 0

View File

@ -1,25 +0,0 @@
{
"MuranoEnvironments.list_environments": [
{
"runner": {
"type": "constant",
"times": 10,
"concurrency": 2
},
"context": {
"users": {
"tenants": 2,
"users_per_tenant": 2
},
"murano_environments": {
"environments_per_tenant": 2
}
},
"sla": {
"failure_rate": {
"max": 0
}
}
}
]
}

View File

@ -1,16 +0,0 @@
---
MuranoEnvironments.list_environments:
-
runner:
type: "constant"
times: 10
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 2
murano_environments:
environments_per_tenant: 2
sla:
failure_rate:
max: 0

View File

@ -1,27 +0,0 @@
{
"MuranoPackages.package_lifecycle": [
{
"args": {
"package": "rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/",
"body": {"categories": ["Web"]},
"operation": "add"
},
"runner": {
"type": "constant",
"times": 5,
"concurrency": 2
},
"context": {
"users": {
"tenants": 2,
"users_per_tenant": 1
}
},
"sla": {
"failure_rate": {
"max": 0
}
}
}
]
}

View File

@ -1,18 +0,0 @@
---
MuranoPackages.package_lifecycle:
-
args:
package: "rally-jobs/extra/murano/applications/HelloReporter/io.murano.apps.HelloReporter/"
body: {"categories": ["Web"]}
operation: "add"
runner:
type: "constant"
times: 5
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 1
sla:
failure_rate:
max: 0

View File

@ -359,17 +359,6 @@ class Sahara(ResourceManager):
return self.client.node_group_templates.list()
class Murano(ResourceManager):
REQUIRED_SERVICE = consts.Service.MURANO
def list_environments(self):
return self.client.environments.list()
def list_packages(self):
return self.client.packages.list(include_disabled=True)
class Designate(ResourceManager):
REQUIRED_SERVICE = consts.Service.DESIGNATE
@ -563,8 +552,6 @@ def check_resource(resources_mgs, compare_with, json_output):
and resource["resource_name"] == "volume"
and resource["id"].get("name") in volume_names)
or resource["cls"] == "murano"
# Glance has issues with uWSGI integration...
# or resource["cls"] == "glance"

View File

@ -877,23 +877,6 @@ class OSClientsTestCase(test.TestCase):
"some_service": "__unknown__"},
clients.services())
def test_murano(self):
fake_murano = fakes.FakeMuranoClient()
mock_murano = mock.Mock()
mock_murano.client.Client.return_value = fake_murano
self.assertNotIn("murano", self.clients.cache)
with mock.patch.dict("sys.modules", {"muranoclient": mock_murano}):
client = self.clients.murano()
self.assertEqual(fake_murano, client)
self.service_catalog.url_for.assert_called_once_with(
service_type="application-catalog",
region_name=self.credential.region_name
)
kw = {"endpoint": self.service_catalog.url_for.return_value,
"token": self.auth_ref.auth_token}
mock_murano.client.Client.assert_called_once_with("1", **kw)
self.assertEqual(fake_murano, self.clients.cache["murano"])
@mock.patch("%s.Keystone.get_session" % PATH)
@ddt.data(
{},

View File

@ -145,10 +145,6 @@ class FakeGoal(FakeResource):
pass
class FakeMurano(FakeResource):
pass
class FakeFloatingIP(FakeResource):
pass
@ -485,14 +481,6 @@ class FakeGoalManager(FakeManager):
return self.cache[key]
class FakePackageManager(FakeManager):
def create(self, package_descr, package_arch, package_class=FakeMurano):
package = self._cache(package_class(self))
package.name = list(package_arch.keys())[0]
return package
class FakeFloatingIPsManager(FakeManager):
def create(self):
@ -977,12 +965,6 @@ class FakeGlanceClient(object):
self.version = version
class FakeMuranoClient(object):
def __init__(self):
self.packages = FakePackageManager()
class FakeCinderClient(object):
def __init__(self):
@ -1533,7 +1515,6 @@ class FakeClients(object):
self._trove = None
self._mistral = None
self._swift = None
self._murano = None
self._monasca = None
self._ec2 = None
self._senlin = None
@ -1618,11 +1599,6 @@ class FakeClients(object):
self._swift = FakeSwiftClient()
return self._swift
def murano(self):
if not self._murano:
self._murano = FakeMuranoClient()
return self._murano
def ec2(self):
if not self._ec2:
self._ec2 = FakeEC2Client()

View File

@ -1,91 +0,0 @@
# Copyright 2015: Mirantis Inc.
# All Rights Reserved.
#
# 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 unittest import mock
from rally_openstack.task.contexts.murano import murano_environments
from rally_openstack.task.scenarios.murano import utils as murano_utils
from tests.unit import test
CTX = "rally_openstack.task.contexts.murano.murano_environments"
SCN = "rally_openstack.task.scenarios"
class MuranoEnvironmentGeneratorTestCase(test.TestCase):
def setUp(self):
super(MuranoEnvironmentGeneratorTestCase, self).setUp()
@staticmethod
def _get_context():
return {
"config": {
"users": {
"tenants": 2,
"users_per_tenant": 1,
"concurrent": 1,
},
"murano_environments": {
"environments_per_tenant": 1
}
},
"admin": {
"credential": mock.MagicMock()
},
"task": mock.MagicMock(),
"owner_id": "foo_uuid",
"users": [
{
"id": "user_0",
"tenant_id": "tenant_0",
"credential": mock.MagicMock()
},
{
"id": "user_1",
"tenant_id": "tenant_1",
"credential": mock.MagicMock()
}
],
"tenants": {
"tenant_0": {"name": "tenant_0_name"},
"tenant_1": {"name": "tenant_1_name"}
}
}
@mock.patch("%s.murano.utils.MuranoScenario._create_environment" % SCN)
def test_setup(self, mock_create_env):
murano_ctx = murano_environments.EnvironmentGenerator(
self._get_context())
murano_ctx.setup()
self.assertEqual(2, len(murano_ctx.context["tenants"]))
tenant_id = murano_ctx.context["users"][0]["tenant_id"]
self.assertEqual([mock_create_env.return_value],
murano_ctx.context["tenants"][tenant_id][
"environments"])
@mock.patch("%s.murano.utils.MuranoScenario._create_environment" % SCN)
@mock.patch("%s.resource_manager.cleanup" % CTX)
def test_cleanup(self, mock_cleanup, mock_create_env):
murano_ctx = murano_environments.EnvironmentGenerator(
self._get_context())
murano_ctx.setup()
murano_ctx.cleanup()
mock_cleanup.assert_called_once_with(
names=["murano.environments"],
users=murano_ctx.context["users"],
superclass=murano_utils.MuranoScenario,
task_id="foo_uuid")

View File

@ -1,118 +0,0 @@
# Copyright 2015: Mirantis Inc.
# All Rights Reserved.
#
# 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 unittest import mock
from rally_openstack.task.contexts.murano import murano_packages
from tests.unit import test
CTX = "rally_openstack.task.contexts.murano.murano_packages"
class MuranoPackageGeneratorTestCase(test.TestCase):
def setUp(self):
super(MuranoPackageGeneratorTestCase, self).setUp()
@staticmethod
def _get_context():
return {
"config": {
"users": {
"tenants": 2,
"users_per_tenant": 1,
"concurrent": 1,
},
"murano_packages": {
"app_package": (
"rally-jobs/extra/murano/"
"applications/HelloReporter/"
"io.murano.apps.HelloReporter.zip")
}
},
"admin": {
"credential": mock.MagicMock()
},
"task": mock.MagicMock(),
"owner_id": "foo_uuid",
"users": [
{
"id": "user_0",
"tenant_id": "tenant_0",
"credential": "credential"
},
{
"id": "user_1",
"tenant_id": "tenant_1",
"credential": "credential"
}
],
"tenants": {
"tenant_0": {"name": "tenant_0_name"},
"tenant_1": {"name": "tenant_1_name"}
}
}
@mock.patch("%s.osclients" % CTX)
def test_setup(self, mock_osclients):
mock_app = mock.MagicMock(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()
self.assertEqual(2, len(murano_ctx.context["tenants"]))
tenant_id = murano_ctx.context["users"][0]["tenant_id"]
self.assertEqual([mock_app],
murano_ctx.context["tenants"][tenant_id]["packages"])
@mock.patch("%s.osclients" % CTX)
@mock.patch("%s.resource_manager.cleanup" % CTX)
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"],
superclass=murano_packages.PackageGenerator,
task_id="foo_uuid")
@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"],
superclass=murano_packages.PackageGenerator,
task_id="foo_uuid")

View File

@ -1,126 +0,0 @@
# Copyright 2015: Mirantis Inc.
# All Rights Reserved.
#
# 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 unittest import mock
from rally_openstack.task.scenarios.murano import environments
from tests.unit import test
MURANO_SCENARIO = ("rally_openstack.task.scenarios.murano."
"environments")
class MuranoEnvironmentsTestCase(test.ScenarioTestCase):
def _get_context(self):
self.context.update({
"tenant": {
"packages": [mock.MagicMock(fully_qualified_name="fake")]
},
"user": {
"tenant_id": "fake_tenant_id"
},
"config": {
"murano_packages": {
"app_package": (
"rally-jobs/extra/murano/"
"applications/HelloReporter/"
"io.murano.apps.HelloReporter.zip")
}
}
})
return self.context
def test_list_environments(self):
TEST_TARGET = "ListEnvironments"
list_env_module = ("{}.{}.{}").format(MURANO_SCENARIO,
TEST_TARGET,
"_list_environments")
scenario = environments.ListEnvironments(self.context)
with mock.patch(list_env_module) as mock_list_env:
scenario.run()
mock_list_env.assert_called_once_with()
def test_create_and_delete_environment(self):
TEST_TARGET = "CreateAndDeleteEnvironment"
generate_random_name_module = ("{}.{}.{}").format(
MURANO_SCENARIO, TEST_TARGET, "generate_random_name")
create_env_module = ("{}.{}.{}").format(MURANO_SCENARIO,
TEST_TARGET,
"_create_environment")
create_session_module = ("{}.{}.{}").format(MURANO_SCENARIO,
TEST_TARGET,
"_create_session")
delete_env_module = ("{}.{}.{}").format(MURANO_SCENARIO,
TEST_TARGET,
"_delete_environment")
scenario = environments.CreateAndDeleteEnvironment(self.context)
with mock.patch(generate_random_name_module) as mock_random_name:
with mock.patch(create_env_module) as mock_create_env:
with mock.patch(create_session_module) as mock_create_session:
with mock.patch(delete_env_module) as mock_delete_env:
fake_env = mock.Mock(id="fake_id")
mock_create_env.return_value = fake_env
mock_random_name.return_value = "foo"
scenario.run()
mock_create_env.assert_called_once_with()
mock_create_session.assert_called_once_with(
fake_env.id)
mock_delete_env.assert_called_once_with(
fake_env)
def test_create_and_deploy_environment(self):
TEST_TARGET = "CreateAndDeployEnvironment"
create_env_module = ("{}.{}.{}").format(MURANO_SCENARIO,
TEST_TARGET,
"_create_environment")
create_session_module = ("{}.{}.{}").format(MURANO_SCENARIO,
TEST_TARGET,
"_create_session")
create_service_module = ("{}.{}.{}").format(MURANO_SCENARIO,
TEST_TARGET,
"_create_service")
deploy_env_module = ("{}.{}.{}").format(MURANO_SCENARIO,
TEST_TARGET,
"_deploy_environment")
scenario = environments.CreateAndDeployEnvironment(self.context)
with mock.patch(create_env_module) as mock_create_env:
with mock.patch(create_session_module) as mock_create_session:
with mock.patch(create_service_module) as mock_create_service:
with mock.patch(deploy_env_module) as mock_deploy_env:
fake_env = mock.MagicMock(id="fake_env_id")
mock_create_env.return_value = fake_env
fake_session = mock.Mock(id="fake_session_id")
mock_create_session.return_value = fake_session
scenario.context = self._get_context()
scenario.context["tenants"] = {
"fake_tenant_id": {
"packages": [mock.MagicMock()]
}
}
scenario.run(1)
mock_create_env.assert_called_once_with()
mock_create_session.assert_called_once_with(
fake_env.id)
mock_create_service.assert_called_once_with(
fake_env,
fake_session,
"fake")
mock_deploy_env.assert_called_once_with(
fake_env, fake_session)

View File

@ -1,86 +0,0 @@
# Copyright 2015: Mirantis Inc.
# All Rights Reserved.
#
# 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 unittest import mock
from rally_openstack.task.scenarios.murano import packages
from tests.unit import test
MURANO_SCENARIO = ("rally_openstack.task.scenarios.murano."
"packages.MuranoPackages")
class MuranoPackagesTestCase(test.TestCase):
def setUp(self):
super(MuranoPackagesTestCase, self).setUp()
self.mock_remove = mock.patch("os.remove")
self.mock_remove.start()
def tearDown(self):
super(MuranoPackagesTestCase, self).tearDown()
self.mock_remove.stop()
def mock_modules(self, scenario):
scenario._import_package = mock.Mock()
scenario._zip_package = mock.Mock()
scenario._list_packages = mock.Mock()
scenario._delete_package = mock.Mock()
scenario._update_package = mock.Mock()
scenario._filter_applications = mock.Mock()
def test_make_zip_import_and_list_packages(self):
scenario = packages.ImportAndListPackages()
self.mock_modules(scenario)
scenario.run("foo_package.zip")
scenario._import_package.assert_called_once_with(
scenario._zip_package.return_value)
scenario._zip_package.assert_called_once_with("foo_package.zip")
scenario._list_packages.assert_called_once_with(
include_disabled=False)
def test_import_and_delete_package(self):
scenario = packages.ImportAndDeletePackage()
self.mock_modules(scenario)
fake_package = mock.Mock()
scenario._import_package.return_value = fake_package
scenario.run("foo_package.zip")
scenario._import_package.assert_called_once_with(
scenario._zip_package.return_value)
scenario._delete_package.assert_called_once_with(fake_package)
def test_package_lifecycle(self):
scenario = packages.PackageLifecycle()
self.mock_modules(scenario)
fake_package = mock.Mock()
scenario._import_package.return_value = fake_package
scenario.run("foo_package.zip", {"category": "Web"}, "add")
scenario._import_package.assert_called_once_with(
scenario._zip_package.return_value)
scenario._update_package.assert_called_once_with(
fake_package, {"category": "Web"}, "add")
scenario._delete_package.assert_called_once_with(fake_package)
def test_import_and_filter_applications(self):
scenario = packages.ImportAndFilterApplications()
self.mock_modules(scenario)
fake_package = mock.Mock()
scenario._import_package.return_value = fake_package
scenario.run("foo_package.zip", {"category": "Web"})
scenario._import_package.assert_called_once_with(
scenario._zip_package.return_value)
scenario._filter_applications.assert_called_once_with(
{"category": "Web"}
)

View File

@ -1,228 +0,0 @@
# Copyright 2015: Mirantis Inc.
# All Rights Reserved.
#
# 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 unittest import mock
from rally.common import cfg
from rally_openstack.task.scenarios.murano import utils
from tests.unit import test
MRN_UTILS = "rally_openstack.task.scenarios.murano.utils"
CONF = cfg.CONF
class MuranoScenarioTestCase(test.ScenarioTestCase):
def test_list_environments(self):
self.clients("murano").environments.list.return_value = []
scenario = utils.MuranoScenario(context=self.context)
return_environments_list = scenario._list_environments()
self.assertEqual([], return_environments_list)
self._test_atomic_action_timer(scenario.atomic_actions(),
"murano.list_environments")
def test_create_environments(self):
self.clients("murano").environments.create = mock.Mock()
scenario = utils.MuranoScenario(context=self.context)
scenario.generate_random_name = mock.Mock()
create_env = scenario._create_environment()
self.assertEqual(
create_env,
self.clients("murano").environments.create.return_value)
self.clients("murano").environments.create.assert_called_once_with(
{"name": scenario.generate_random_name.return_value})
self._test_atomic_action_timer(scenario.atomic_actions(),
"murano.create_environment")
def test_delete_environment(self):
environment = mock.Mock(id="id")
self.clients("murano").environments.delete.return_value = "ok"
scenario = utils.MuranoScenario(context=self.context)
scenario._delete_environment(environment)
self.clients("murano").environments.delete.assert_called_once_with(
environment.id
)
def test_create_session(self):
self.clients("murano").sessions.configure.return_value = "sess"
scenario = utils.MuranoScenario(context=self.context)
create_sess = scenario._create_session("id")
self.assertEqual("sess", create_sess)
self._test_atomic_action_timer(scenario.atomic_actions(),
"murano.create_session")
def test__create_service(self,):
self.clients("murano").services.post.return_value = "app"
mock_env = mock.Mock(id="ip")
mock_sess = mock.Mock(id="ip")
scenario = utils.MuranoScenario(context=self.context)
create_app = scenario._create_service(mock_env, mock_sess,
"fake_full_name")
self.assertEqual("app", create_app)
self._test_atomic_action_timer(scenario.atomic_actions(),
"murano.create_service")
def test_deploy_environment(self):
environment = mock.Mock(id="id")
session = mock.Mock(id="id")
self.clients("murano").sessions.deploy.return_value = "ok"
scenario = utils.MuranoScenario(context=self.context)
scenario._deploy_environment(environment, session)
self.clients("murano").sessions.deploy.assert_called_once_with(
environment.id, session.id
)
config = CONF.openstack
self.mock_wait_for_status.mock.assert_called_once_with(
environment,
update_resource=self.mock_get_from_manager.mock.return_value,
ready_statuses=["READY"],
check_interval=config.murano_deploy_environment_check_interval,
timeout=config.murano_deploy_environment_timeout)
self.mock_get_from_manager.mock.assert_called_once_with(
["DEPLOY FAILURE"])
self._test_atomic_action_timer(scenario.atomic_actions(),
"murano.deploy_environment")
@mock.patch(MRN_UTILS + ".open",
side_effect=mock.mock_open(read_data="Key: value"),
create=True)
def test_read_from_file(self, mock_open):
utility = utils.MuranoPackageManager({"uuid": "fake_task_id"})
data = utility._read_from_file("filename")
expected_data = {"Key": "value"}
self.assertEqual(expected_data, data)
@mock.patch(MRN_UTILS + ".MuranoPackageManager._read_from_file")
@mock.patch(MRN_UTILS + ".MuranoPackageManager._write_to_file")
def test_change_app_fullname(
self, mock_murano_package_manager__write_to_file,
mock_murano_package_manager__read_from_file):
manifest = {"FullName": "app.name_abc",
"Classes": {"app.name_abc": "app_class.yaml"}}
mock_murano_package_manager__read_from_file.side_effect = (
[manifest])
utility = utils.MuranoPackageManager({"uuid": "fake_task_id"})
utility._change_app_fullname("tmp/tmpfile/")
mock_murano_package_manager__read_from_file.assert_has_calls(
[mock.call("tmp/tmpfile/manifest.yaml")]
)
mock_murano_package_manager__write_to_file.assert_has_calls(
[mock.call(manifest, "tmp/tmpfile/manifest.yaml")]
)
@mock.patch("zipfile.is_zipfile")
@mock.patch("tempfile.mkdtemp")
@mock.patch("shutil.copytree")
@mock.patch(MRN_UTILS + ".MuranoPackageManager._change_app_fullname")
@mock.patch("%s.pack_dir" % MRN_UTILS)
@mock.patch("shutil.rmtree")
def test_prepare_zip_if_not_zip(
self, mock_shutil_rmtree, mock_pack_dir,
mock_murano_package_manager__change_app_fullname,
mock_shutil_copytree, mock_tempfile_mkdtemp,
mock_zipfile_is_zipfile):
utility = utils.MuranoPackageManager({"uuid": "fake_task_id"})
package_path = "tmp/tmpfile"
mock_zipfile_is_zipfile.return_value = False
mock_tempfile_mkdtemp.return_value = "tmp/tmpfile"
mock_pack_dir.return_value = "tmp/tmpzipfile"
zip_file = utility._prepare_package(package_path)
self.assertEqual("tmp/tmpzipfile", zip_file)
mock_tempfile_mkdtemp.assert_called_once_with()
mock_shutil_copytree.assert_called_once_with(
"tmp/tmpfile",
"tmp/tmpfile/package/"
)
(mock_murano_package_manager__change_app_fullname.
assert_called_once_with("tmp/tmpfile/package/"))
mock_shutil_rmtree.assert_called_once_with("tmp/tmpfile")
@mock.patch("zipfile.is_zipfile")
def test_prepare_zip_if_zip(self, mock_zipfile_is_zipfile):
utility = utils.MuranoPackageManager({"uuid": "fake_task_id"})
package_path = "tmp/tmpfile.zip"
mock_zipfile_is_zipfile.return_value = True
zip_file = utility._prepare_package(package_path)
self.assertEqual("tmp/tmpfile.zip", zip_file)
def test_list_packages(self):
scenario = utils.MuranoScenario()
self.assertEqual(self.clients("murano").packages.list.return_value,
scenario._list_packages())
self._test_atomic_action_timer(scenario.atomic_actions(),
"murano.list_packages")
@mock.patch(MRN_UTILS + ".open", create=True)
def test_import_package(self, mock_open):
self.clients("murano").packages.create.return_value = (
"created_foo_package"
)
scenario = utils.MuranoScenario()
mock_open.return_value = "opened_foo_package.zip"
imp_package = scenario._import_package("foo_package.zip")
self.assertEqual("created_foo_package", imp_package)
self.clients("murano").packages.create.assert_called_once_with(
{}, {"file": "opened_foo_package.zip"})
mock_open.assert_called_once_with("foo_package.zip")
self._test_atomic_action_timer(scenario.atomic_actions(),
"murano.import_package")
def test_delete_package(self):
package = mock.Mock(id="package_id")
scenario = utils.MuranoScenario()
scenario._delete_package(package)
self.clients("murano").packages.delete.assert_called_once_with(
"package_id"
)
self._test_atomic_action_timer(scenario.atomic_actions(),
"murano.delete_package")
def test_update_package(self):
package = mock.Mock(id="package_id")
self.clients("murano").packages.update.return_value = "updated_package"
scenario = utils.MuranoScenario()
upd_package = scenario._update_package(
package, {"tags": ["tag"]}, "add"
)
self.assertEqual("updated_package", upd_package)
self.clients("murano").packages.update.assert_called_once_with(
"package_id",
{"tags": ["tag"]},
"add"
)
self._test_atomic_action_timer(scenario.atomic_actions(),
"murano.update_package")
def test_filter_packages(self):
self.clients("murano").packages.filter.return_value = []
scenario = utils.MuranoScenario()
return_apps_list = scenario._filter_applications(
{"category": "Web"}
)
self.assertEqual([], return_apps_list)
self.clients("murano").packages.filter.assert_called_once_with(
category="Web"
)
self._test_atomic_action_timer(scenario.atomic_actions(),
"murano.filter_applications")

View File

@ -34,7 +34,6 @@ kubernetes===29.0.0
Mako===1.3.2
MarkupSafe===2.1.5
msgpack===1.0.8
murano-pkg-check===0.3.0
netaddr===0.10.1
netifaces===0.11.0
oauthlib===3.2.2
@ -79,7 +78,6 @@ python-magnumclient===4.4.0
python-manilaclient===4.8.0
python-mistralclient===5.2.0
python-monascaclient===2.8.0
python-muranoclient===2.8.0
python-neutronclient===11.2.0
python-novaclient===18.6.0
python-octaviaclient===3.7.0