Fixes silent deletion of environments

Now environment deletion is done as a regular deployment that can fail.
Environments that are deleted, but deletion process has failed remain in database
and shown in dashboard with status 'delete failure'. Environments that are being deleted
has status 'deleting' and do not disappear before they really got deleted on engine side

Also improved status reporting for environments. Now it also reports status of last deployment -
'deploy failure', 'delete failure'

P.S. Functional tests were slightly refactored and fixed to reflect changes
in deletion logic

Change-Id: I05625dd71f7ca9559bb88319b26b122214f15019
Closes-Bug: #1325101
This commit is contained in:
Stan Lagun 2014-07-25 11:06:56 +04:00 committed by Serg Melikyan
parent 2309247b24
commit 56b2d5df27
19 changed files with 283 additions and 219 deletions

3
.gitignore vendored
View File

@ -27,3 +27,6 @@ cover
#Autogenerated Documentation
doc/source/api
#Config file for functional tests
murano/tests/functional/engine/config.conf

View File

@ -16,6 +16,7 @@ from sqlalchemy import desc
from webob import exc
from murano.api.v1 import request_statistics
from murano.api.v1 import sessions
from murano.common import policy
from murano.common import utils
from murano.db import models
@ -123,22 +124,11 @@ class Controller(object):
LOG.debug('Environments:Delete <Id: {0}>'.format(environment_id))
target = {"environment_id": environment_id}
policy.check('delete_environment', request.context, target)
unit = db_session.get_session()
environment = unit.query(models.Environment).get(environment_id)
if environment is None:
LOG.info(_('Environment <EnvId {0}> '
'is not found').format(environment_id))
raise exc.HTTPNotFound
if environment.tenant_id != request.context.tenant:
LOG.info(_('User is not authorized to access '
'this tenant resources.'))
raise exc.HTTPUnauthorized
envs.EnvironmentServices.delete(environment_id,
request.context.auth_token)
sessions_controller = sessions.Controller()
session = sessions_controller.configure(request, environment_id)
session_id = session['id']
envs.EnvironmentServices.delete(environment_id, session_id)
sessions_controller.deploy(request, environment_id, session_id)
@request_statistics.stats_count(API_NAME, 'LastStatus')
def last(self, request, environment_id):
@ -150,7 +140,7 @@ class Controller(object):
session_id)
session = db_session.get_session()
result = {}
for service in services:
for service in services or []:
service_id = service['?']['id']
entity_ids = utils.build_entity_map(service).keys()
last_status = session.query(models.Status). \

View File

@ -49,7 +49,8 @@ class Controller(object):
# no new session can be opened if environment has deploying status
env_status = envs.EnvironmentServices.get_status(environment_id)
if env_status == envs.EnvironmentStatus.deploying:
if env_status in (envs.EnvironmentStatus.DEPLOYING,
envs.EnvironmentStatus.DELETING):
LOG.info(_('Could not open session for environment <EnvId: {0}>,'
'environment has deploying '
'status.').format(environment_id))
@ -113,7 +114,7 @@ class Controller(object):
'<SessionId {1}>.').format(user_id, session_id))
raise exc.HTTPUnauthorized()
if session.state == sessions.SessionState.deploying:
if session.state == sessions.SessionState.DEPLOYING:
LOG.error(_('Session <SessionId: {0}> is in deploying state and '
'could not be deleted').format(session_id))
raise exc.HTTPForbidden()
@ -145,7 +146,7 @@ class Controller(object):
'is invalid').format(session_id))
raise exc.HTTPForbidden()
if session.state != sessions.SessionState.open:
if session.state != sessions.SessionState.OPENED:
LOG.error(_('Session <SessionId {0}> is already deployed or '
'deployment is in progress').format(session_id))
raise exc.HTTPForbidden()

View File

@ -48,21 +48,19 @@ class TaskProcessingEndpoint(object):
LOG.info(_('Starting processing task: {task_desc}').format(
task_desc=anyjson.dumps(s_task)))
result = task['model']
try:
task_executor = TaskExecutor(task)
result = task_executor.execute()
rpc.api().process_result(result)
except Exception as e:
# TODO(gokrokve) report error here
# TODO(slagun) code below needs complete rewrite and redesign
LOG.exception("Error during task execution for tenant %s",
LOG.exception('Error during task execution for tenant %s',
task['tenant_id'])
if task['model']['Objects']:
msg_env = Environment(task['model']['Objects']['?']['id'])
reporter = status_reporter.StatusReporter()
reporter.initialize(msg_env)
reporter.report_error(msg_env, str(e))
rpc.api().process_result(task['model'])
msg_env = Environment(task['id'])
reporter = status_reporter.StatusReporter()
reporter.initialize(msg_env)
reporter.report_error(msg_env, str(e))
finally:
rpc.api().process_result(result, task['id'])
def _prepare_rpc_service(server_id):

View File

@ -26,8 +26,9 @@ class ApiClient(object):
client_target = target.Target('murano', 'results')
self._client = rpc.RPCClient(transport, client_target, timeout=15)
def process_result(self, result):
return self._client.call({}, 'process_result', result=result)
def process_result(self, result, environment_id):
return self._client.call({}, 'process_result', result=result,
environment_id=environment_id)
class EngineClient(object):

View File

@ -23,7 +23,9 @@ from sqlalchemy import desc
from murano.common import config
from murano.common.helpers import token_sanitizer
from murano.db import models
from murano.db.services import environments
from murano.db.services import instances
from murano.db.services import sessions
from murano.db import session
from murano.openstack.common.gettextutils import _ # noqa
from murano.openstack.common import log as logging
@ -38,39 +40,36 @@ LOG = logging.getLogger(__name__)
class ResultEndpoint(object):
@staticmethod
def process_result(context, result):
def process_result(context, result, environment_id):
secure_result = token_sanitizer.TokenSanitizer().sanitize(result)
LOG.debug('Got result from orchestration '
'engine:\n{0}'.format(secure_result))
if not result['Objects']:
LOG.debug('Ignoring result for deleted environment')
return
result_id = result['Objects']['?']['id']
unit = session.get_session()
environment = unit.query(models.Environment).get(result_id)
environment = unit.query(models.Environment).get(environment_id)
if not environment:
LOG.warning(_('Environment result could not be handled, specified '
'environment was not found in database'))
return
if result['Objects'] is None and result.get('ObjectsCopy', {}) is None:
environments.EnvironmentServices.remove(environment_id)
return
environment.description = result
environment.description['Objects']['services'] = \
environment.description['Objects'].get('applications', [])
del environment.description['Objects']['applications']
environment.networking = result.get('networking', {})
if environment.description['Objects'] is not None:
environment.description['Objects']['services'] = \
environment.description['Objects'].pop('applications', [])
# environment.networking = result.get('networking', {})
action_name = 'Deployment'
deleted = False
else:
action_name = 'Deletion'
deleted = True
environment.version += 1
environment.save(unit)
#close session
conf_session = unit.query(models.Session).filter_by(
**{'environment_id': environment.id, 'state': 'deploying'}).first()
conf_session.state = 'deployed'
conf_session.save(unit)
#close deployment
deployment = get_last_deployment(unit, environment.id)
deployment.finished = timeutils.utcnow()
@ -80,7 +79,7 @@ class ResultEndpoint(object):
num_warnings = unit.query(models.Status)\
.filter_by(level='warning', deployment_id=deployment.id).count()
final_status_text = "Deployment finished"
final_status_text = action_name + ' finished'
if num_errors:
final_status_text += " with errors"
@ -94,6 +93,18 @@ class ResultEndpoint(object):
deployment.statuses.append(status)
deployment.save(unit)
#close session
conf_session = unit.query(models.Session).filter_by(
**{'environment_id': environment.id,
'state': 'deploying' if not deleted else 'deleting'}).first()
if num_errors > 0:
conf_session.state = \
sessions.SessionState.DELETE_FAILURE if deleted else \
sessions.SessionState.DEPLOY_FAILURE
else:
conf_session.state = sessions.SessionState.DEPLOYED
conf_session.save(unit)
def notification_endpoint_wrapper(priority='info'):
def wrapper(func):

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import types
from webob import exc
from murano.common import utils
from murano.db.services import environments as envs
@ -46,6 +47,9 @@ class CoreServices(object):
env_description = get_description(environment_id, session_id)
if env_description is None:
return None
if not 'services' in env_description:
return []
@ -65,6 +69,8 @@ class CoreServices(object):
save_environment_description
env_description = get_description(environment_id, session_id)
if env_description is None:
raise exc.HTTPMethodNotAllowed
if not 'services' in env_description:
env_description['services'] = []

View File

@ -14,7 +14,6 @@
import collections
from murano.common import rpc
from murano.common import uuidutils
from murano.db import models
@ -23,9 +22,16 @@ from murano.db import session as db_session
EnvironmentStatus = collections.namedtuple('EnvironmentStatus', [
'ready', 'pending', 'deploying'
'READY', 'PENDING', 'DEPLOYING', 'DEPLOY_FAILURE', 'DELETING',
'DELETE_FAILURE'
])(
ready='ready', pending='pending', deploying='deploying'
READY='ready',
PENDING='pending',
DEPLOYING='deploying',
DEPLOY_FAILURE='deploy failure',
DELETING='deleting',
DELETE_FAILURE='delete failure'
)
DEFAULT_NETWORKS = {
@ -54,31 +60,37 @@ class EnvironmentServices(object):
@staticmethod
def get_status(environment_id):
"""
Environment can have one of three distinguished statuses:
Environment can have one of the following statuses:
- Deploying: there is at least one session with status `deploying`;
- Pending: there is at least one session with status `open`;
- Ready: there is no sessions in status `deploying` or `open`.
- deploying: there is ongoing deployment for environment
- deleting: environment is currently being deleted
- deploy failure: last deployment session has failed
- delete failure: last delete session has failed
- pending: there is at least one session with status `open` and no
errors in previous sessions
- ready: there are no sessions for environment
:param environment_id: Id of environment for which we checking status.
:return: Environment status
"""
#Deploying: there is at least one valid session with status `deploying`
deploying = sessions.SessionServices.get_sessions(
environment_id,
sessions.SessionState.deploying)
if len(deploying) > 0:
return 'deploying'
session_list = sessions.SessionServices.get_sessions(environment_id)
has_opened = False
for session in session_list:
if session.state == sessions.SessionState.DEPLOYING:
return EnvironmentStatus.DEPLOYING
elif session.state == sessions.SessionState.DELETING:
return EnvironmentStatus.DELETING
elif session.state == sessions.SessionState.DEPLOY_FAILURE:
return EnvironmentStatus.DEPLOY_FAILURE
elif session.state == sessions.SessionState.DELETE_FAILURE:
return EnvironmentStatus.DELETE_FAILURE
elif session.state == sessions.SessionState.OPENED:
has_opened = True
if has_opened:
return EnvironmentStatus.PENDING
#Pending: there is at least one valid session with status `open`;
open = sessions.SessionServices.get_sessions(
environment_id,
sessions.SessionState.open)
if len(open) > 0:
return 'pending'
#Ready: there are no sessions in status `deploying` or `open`
return 'ready'
return EnvironmentStatus.READY
@staticmethod
def create(environment_params, tenant_id):
@ -118,30 +130,27 @@ class EnvironmentServices(object):
return environment
@staticmethod
def delete(environment_id, token):
def delete(environment_id, session_id):
"""
Deletes environment and notify orchestration engine about deletion
:param environment_id: Environment that is going to be deleted
:param token: OpenStack auth token
"""
env_description = EnvironmentServices.get_environment_description(
environment_id, session_id, False)
env_description['Objects'] = None
EnvironmentServices.save_environment_description(
session_id, env_description, False)
@staticmethod
def remove(environment_id):
unit = db_session.get_session()
environment = unit.query(models.Environment).get(environment_id)
#preparing data for removal from conductor
env = environment.description
env['Objects'] = None
data = {
'model': env,
'token': token,
'tenant_id': environment.tenant_id
}
rpc.engine().handle_task(data)
with unit.begin():
unit.delete(environment)
if environment:
with unit.begin():
unit.delete(environment)
@staticmethod
def get_environment_description(environment_id, session_id=None,
@ -162,7 +171,7 @@ class EnvironmentServices(object):
if session_id:
session = unit.query(models.Session).get(session_id)
if sessions.SessionServices.validate(session):
if session.state != sessions.SessionState.deployed:
if session.state != sessions.SessionState.DEPLOYED:
env_description = session.description
else:
env = unit.query(models.Environment)\

View File

@ -20,9 +20,15 @@ from murano.db import session as db_session
SessionState = collections.namedtuple('SessionState', [
'open', 'deploying', 'deployed'
'OPENED', 'DEPLOYING', 'DEPLOYED', 'DEPLOY_FAILURE', 'DELETING',
'DELETE_FAILURE'
])(
open='open', deploying='deploying', deployed='deployed'
OPENED='opened',
DEPLOYING='deploying',
DEPLOYED='deployed',
DEPLOY_FAILURE='deploy failure',
DELETING='deleting',
DELETE_FAILURE='delete failure'
)
@ -41,17 +47,18 @@ class SessionServices(object):
unit = db_session.get_session()
# Here we duplicate logic for reducing calls to database
# Checks for validation is same as in validate.
environment = unit.query(models.Environment).get(environment_id)
return unit.query(models.Session).filter(
query = unit.query(models.Session).filter(
#Get all session for this environment
models.Session.environment_id == environment_id,
#in this state, if state is not specified return in all states
models.Session.state.in_(SessionState
if state is None else [state]),
#Only sessions with same version as current env version are valid
models.Session.version == environment.version
).all()
)
if state:
#in this state, if state is not specified return in all states
query = query.filter(models.Session.state == state),
return query.order_by(models.Session.version.desc(),
models.Session.updated.desc()).all()
@staticmethod
def create(environment_id, user_id):
@ -68,7 +75,7 @@ class SessionServices(object):
session = models.Session()
session.environment_id = environment.id
session.user_id = user_id
session.state = SessionState.open
session.state = SessionState.OPENED
# used for checking if other sessions was deployed before this one
session.version = environment.version
# all changes to environment is stored here, and translated to
@ -101,9 +108,9 @@ class SessionServices(object):
#if other session is deploying now current session is invalid
other_is_deploying = unit.query(models.Session).filter_by(
environment_id=session.environment_id, state=SessionState.deploying
environment_id=session.environment_id, state=SessionState.DEPLOYING
).count() > 0
if session.state == SessionState.open and other_is_deploying:
if session.state == SessionState.OPENED and other_is_deploying:
return False
return True
@ -123,32 +130,40 @@ class SessionServices(object):
environment = unit.query(models.Environment).get(
session.environment_id)
task = {
'action': {
deleted = session.description['Objects'] is None
action = None
if not deleted:
action = {
'object_id': environment.id,
'method': 'deploy',
'args': {}
},
}
task = {
'action': action,
'model': session.description,
'token': token,
'tenant_id': environment.tenant_id
'tenant_id': environment.tenant_id,
'id': environment.id
}
task['model']['Objects']['?']['id'] = environment.id
task['model']['Objects']['applications'] = \
task['model']['Objects'].get('services', [])
if not deleted:
task['model']['Objects']['?']['id'] = environment.id
task['model']['Objects']['applications'] = \
task['model']['Objects'].get('services', [])
if 'services' in task['model']['Objects']:
del task['model']['Objects']['services']
if 'services' in task['model']['Objects']:
del task['model']['Objects']['services']
session.state = SessionState.deploying
session.state = SessionState.DELETING if deleted \
else SessionState.DEPLOYING
deployment = models.Deployment()
deployment.environment_id = session.environment_id
deployment.description = token_sanitizer.TokenSanitizer().sanitize(
dict(session.description.get('Objects')))
session.description.get('Objects'))
status = models.Status()
status.text = "Deployment scheduled"
status.level = "info"
status.text = ('Delete' if deleted else 'Deployment') + ' scheduled'
status.level = 'info'
deployment.statuses.append(status)
with unit.begin():

View File

@ -263,10 +263,7 @@ class MuranoDslExecutor(object):
for obj in objects_to_clean:
methods = obj.type.find_all_methods('destroy')
for method in methods:
try:
method.invoke(self, obj, {})
except Exception:
pass
method.invoke(self, obj, {})
finally:
self._object_store = backup

View File

@ -15,6 +15,7 @@
import json
import os
import requests
import time
import uuid
from tempest import clients
@ -45,8 +46,24 @@ class MuranoClient(rest_client.RestClient):
return resp, json.loads(body)
def delete_environment(self, environment_id):
return self.delete('v1/environments/{0}'.format(environment_id))
def delete_environment(self, environment_id, timeout=180):
def _is_exist():
try:
resp, _ = self.get('v1/environments/{0}'.format(
environment_id))
except exceptions.NotFound:
return False
return resp.status == 200
env_deleted = not _is_exist()
self.delete('v1/environments/{0}'.format(environment_id))
start_time = time.time()
while env_deleted is not True:
if timeout and time.time() - start_time > timeout:
raise Exception('Environment was not deleted')
time.sleep(5)
env_deleted = not _is_exist()
def update_environment(self, environment_id):
post_body = '{"name": "%s"}' % ("changed-environment-name")

View File

@ -14,12 +14,14 @@
import json
import os
import requests
import socket
import time
import urlparse
import uuid
import requests
import testresources
import testtools
import time
import uuid
from heatclient import client as heatclient
from keystoneclient.v2_0 import client as ksclient
@ -31,66 +33,70 @@ CONF = cfg.cfg.CONF
class Client(object):
def __init__(self, user, password, tenant, auth_url, murano_url):
self.auth = ksclient.Client(username=user, password=password,
tenant_name=tenant, auth_url=auth_url)
self.endpoint = murano_url
self.auth = ksclient.Client(
username=user, password=password,
tenant_name=tenant, auth_url=auth_url
)
self.endpoint = urlparse.urljoin(murano_url, 'v1/')
self.headers = {
'X-Auth-Token': self.auth.auth_token,
'Content-type': 'application/json'
}
def get_url(self, url_part=None):
return urlparse.urljoin(self.endpoint, url_part)
def create_environment(self, name):
post_body = {'name': name}
resp = requests.post(self.endpoint + 'environments',
data=json.dumps(post_body),
headers=self.headers)
endpoint = self.get_url('environments')
body = json.dumps({'name': name})
return resp.json()
return requests.post(endpoint, data=body, headers=self.headers).json()
def delete_environment(self, environment_id):
endpoint = '{0}environments/{1}'.format(self.endpoint, environment_id)
return requests.delete(endpoint, headers=self.headers)
def delete_environment(self, environment_id, timeout=180):
endpoint = self.get_url('environments/%s' % environment_id)
def _is_exist():
resp = requests.get(endpoint, headers=self.headers)
return resp.status_code == requests.codes.ok
env_deleted = not _is_exist()
requests.delete(endpoint, headers=self.headers)
start_time = time.time()
while env_deleted is not True:
if timeout and time.time() - start_time > timeout:
raise Exception('Environment was not deleted')
time.sleep(5)
env_deleted = not _is_exist()
def get_environment(self, environment_id):
return requests.get('{0}environments/{1}'.format(self.endpoint,
environment_id),
headers=self.headers).json()
endpoint = self.get_url('environments/%s' % environment_id)
return requests.get(endpoint, headers=self.headers).json()
def create_session(self, environment_id):
post_body = None
endpoint = '{0}environments/{1}/configure'.format(self.endpoint,
environment_id)
return requests.post(endpoint, data=post_body,
headers=self.headers).json()
endpoint = self.get_url('environments/%s/configure' % environment_id)
return requests.post(endpoint, headers=self.headers).json()
def deploy_session(self, environment_id, session_id):
endpoint = '{0}environments/{1}/sessions/{2}/deploy'.format(
self.endpoint, environment_id, session_id)
return requests.post(endpoint, data=None, headers=self.headers)
endpoint = self.get_url('environments/{0}/sessions/{1}/deploy'.format(
environment_id, session_id))
return requests.post(endpoint, headers=self.headers)
def create_service(self, environment_id, session_id, json_data):
endpoint = self.get_url('environments/%s/services' % environment_id)
body = json.dumps(json_data)
headers = self.headers.copy()
headers.update({'x-configuration-session': session_id})
headers['x-configuration-session'] = session_id
endpoint = '{0}environments/{1}/services'.format(self.endpoint,
environment_id)
return requests.post(endpoint, data=json.dumps(json_data),
headers=headers).json()
return requests.post(endpoint, data=body, headers=headers).json()
def delete_service(self, environment_id, session_id, service_id):
endpoint = self.get_url('environments/{0}/services/{1}'.format(
environment_id, service_id
))
headers = self.headers.copy()
headers.update({'x-configuration-session': session_id})
endpoint = '{0}environments/{1}/services/{2}'.format(
self.endpoint, environment_id, service_id)
headers['x-configuration-session'] = session_id
requests.delete(endpoint, headers=headers)
@ -98,7 +104,6 @@ class Client(object):
environment = self.get_environment(environment_id)
start_time = time.time()
while environment['status'] != 'ready':
if time.time() - start_time > 1200:
return
@ -112,11 +117,19 @@ class Client(object):
for service in environment['services']]
def deployments_list(self, environment_id):
endpoint = '{0}environments/{1}/deployments'.format(self.endpoint,
environment_id)
endpoint = self.get_url('environments/%s/deployments' % environment_id)
response = requests.get(endpoint, headers=self.headers)
return response.json()['deployments']
return requests.get(endpoint,
headers=self.headers).json()['deployments']
def upload_package(self, name, package, description):
endpoint = self.get_url('catalog/packages')
body = {'JsonString': json.dumps(description)}
files = {name: open(package, 'rb')}
headers = self.headers.copy()
del headers['Content-type']
resp = requests.post(endpoint, data=body, files=files, headers=headers)
return resp.json()['id']
class MuranoBase(testtools.TestCase, testtools.testcase.WithAttributes,
@ -143,49 +156,38 @@ class MuranoBase(testtools.TestCase, testtools.testcase.WithAttributes,
cls.heat_client = heatclient.Client('1', endpoint=heat_url,
token=cls.client.auth.auth_token)
cls.location = os.path.realpath(
os.path.join(os.getcwd(), os.path.dirname(__file__)))
cls.pkgs_path = os.path.abspath(os.path.join(
os.path.dirname(__file__),
os.path.pardir,
'murano-app-incubator'
))
cls.packages_path = '/'.join(cls.location.split('/')[:-1:])
def upload_package(package_name, body, app):
#TODO(efedorova): Use muranoclient to upload packages
files = {'%s' % package_name: open(
os.path.join(cls.packages_path, app), 'rb')}
post_body = {'JsonString': json.dumps(body)}
request_url = '{endpoint}{url}'.format(
endpoint=CONF.murano.murano_url,
url='catalog/packages')
headers = cls.client.headers.copy()
del headers['Content-type']
return requests.post(request_url,
files=files,
data=post_body,
headers=headers).json()['id']
cls.postgre_id = upload_package(
cls.postgre_id = cls.client.upload_package(
'PostgreSQL',
{"categories": ["Databases"], "tags": ["tag"]},
'murano-app-incubator/io.murano.apps.PostgreSql.zip')
cls.apache_id = upload_package(
os.path.join(cls.pkgs_path, 'io.murano.apps.PostgreSql.zip'),
{'categories': ['Databases'], 'tags': ['tag']}
)
cls.apache_id = cls.client.upload_package(
'Apache',
{"categories": ["Application Servers"], "tags": ["tag"]},
'murano-app-incubator/io.murano.apps.apache.Apache.zip')
cls.tomcat_id = upload_package(
os.path.join(cls.pkgs_path, 'io.murano.apps.apache.Apache.zip'),
{'categories': ['Application Servers'], 'tags': ['tag']}
)
cls.tomcat_id = cls.client.upload_package(
'Tomcat',
{"categories": ["Application Servers"], "tags": ["tag"]},
'murano-app-incubator/io.murano.apps.apache.Tomcat.zip')
cls.telnet_id = upload_package(
os.path.join(cls.pkgs_path, 'io.murano.apps.apache.Tomcat.zip'),
{'categories': ['Application Servers'], 'tags': ['tag']}
)
cls.telnet_id = cls.client.upload_package(
'Telnet',
{"categories": ["Web"], "tags": ["tag"]},
'murano-app-incubator/io.murano.apps.linux.Telnet.zip')
cls.ad_id = upload_package(
os.path.join(cls.pkgs_path, 'io.murano.apps.linux.Telnet.zip'),
{'categories': ['Web'], 'tags': ['tag']}
)
cls.ad_id = cls.client.upload_package(
'Active Directory',
{"categories": ["Microsoft Services"], "tags": ["tag"]},
'murano-app-incubator/io.murano.windows.ActiveDirectory.zip')
os.path.join(cls.pkgs_path,
'io.murano.windows.ActiveDirectory.zip'),
{'categories': ['Microsoft Services'], 'tags': ['tag']}
)
def setUp(self):
super(MuranoBase, self).setUp()

View File

@ -1,8 +0,0 @@
[murano]
auth_url = http://172.16.116.5:5000/v2.0/
user = kate
password = swordfish
tenant = kate
murano_url = http://localhost:8082/v1/
linux_image = default_linux
windows_image = default_windows

View File

@ -0,0 +1,21 @@
[murano]
# keystone url
#auth_url = http://127.0.0.1:5000/v2.0/
# keystone user
#user = admin
# password for keystone user
#password = pass
# keystone tenant
#tenant = admin
# murano url
#murano_url = http://localhost:8082
# image for linux services
#linux_image = default_linux
# image for windows services
#windows_image = default_windows

View File

@ -23,8 +23,6 @@ import murano.tests.unit.utils as test_utils
class TestEnvironmentApi(tb.ControllerTest, tb.MuranoApiTestCase):
RPC_IMPORT = 'murano.db.services.environments.rpc'
def setUp(self):
super(TestEnvironmentApi, self).setUp()
self.controller = environments.Controller()
@ -165,8 +163,9 @@ class TestEnvironmentApi(tb.ControllerTest, tb.MuranoApiTestCase):
self._set_policy_rules(
{'delete_environment': '@'}
)
self.expect_policy_check('delete_environment',
{'environment_id': '12345'})
self.expect_policy_check(
'delete_environment', {'environment_id': '12345'}
)
fake_now = timeutils.utcnow()
expected = dict(
@ -188,6 +187,8 @@ class TestEnvironmentApi(tb.ControllerTest, tb.MuranoApiTestCase):
test_utils.save_models(e)
rpc_task = {
'id': '12345',
'action': None,
'tenant_id': self.tenant,
'model': {'Attributes': {}, 'Objects': None},
'token': None

View File

@ -17,8 +17,8 @@ import mock
from murano.engine.system import agent
from murano.engine.system import agent_listener
from murano.tests.dsl.foundation import object_model as om
from murano.tests.dsl.foundation import test_case
from murano.tests.unit.dsl.foundation import object_model as om
from murano.tests.unit.dsl.foundation import test_case
class TestAgentListener(test_case.DslTestCase):

View File

@ -67,7 +67,7 @@ def verify_session(func):
'is invalid').format(session_id))
raise exc.HTTPForbidden()
if session.state == sessions.SessionState.deploying:
if session.state == sessions.SessionState.DEPLOYING:
LOG.info(_('Session <SessionId {0}> is already in '
'deployment state').format(session_id))
raise exc.HTTPForbidden()