Merge "Environment Template. Create an environment from a template"
This commit is contained in:
commit
13c160fb7d
@ -117,6 +117,10 @@ class API(wsgi.Router):
|
|||||||
controller=templates_resource,
|
controller=templates_resource,
|
||||||
action='delete',
|
action='delete',
|
||||||
conditions={'method': ['DELETE']})
|
conditions={'method': ['DELETE']})
|
||||||
|
mapper.connect('/templates/{env_template_id}/create-environment',
|
||||||
|
controller=templates_resource,
|
||||||
|
action='create_environment',
|
||||||
|
conditions={'method': ['POST']})
|
||||||
|
|
||||||
applications_resource = template_applications.create_resource()
|
applications_resource = template_applications.create_resource()
|
||||||
mapper.connect('/templates/{env_template_id}/services',
|
mapper.connect('/templates/{env_template_id}/services',
|
||||||
|
@ -15,13 +15,16 @@
|
|||||||
from oslo.db import exception as db_exc
|
from oslo.db import exception as db_exc
|
||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
from murano.api.v1 import environments as envs
|
from murano.api.v1 import environments as envs_api
|
||||||
from murano.api.v1 import request_statistics
|
from murano.api.v1 import request_statistics
|
||||||
from murano.common.i18n import _
|
from murano.common.i18n import _
|
||||||
from murano.common import policy
|
from murano.common import policy
|
||||||
|
from murano.common import utils
|
||||||
from murano.common import wsgi
|
from murano.common import wsgi
|
||||||
from murano.db.services import core_services
|
from murano.db.services import core_services
|
||||||
from murano.db.services import environment_templates as env_temps
|
from murano.db.services import environment_templates as env_temps
|
||||||
|
from murano.db.services import environments as envs
|
||||||
|
from murano.db.services import sessions
|
||||||
from murano.openstack.common import log as logging
|
from murano.openstack.common import log as logging
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
@ -59,7 +62,7 @@ class Controller(object):
|
|||||||
policy.check('create_env_template', request.context)
|
policy.check('create_env_template', request.context)
|
||||||
try:
|
try:
|
||||||
LOG.debug('ENV TEMP NAME: {0}>'.format(body['name']))
|
LOG.debug('ENV TEMP NAME: {0}>'.format(body['name']))
|
||||||
if not envs.VALID_NAME_REGEX.match(str(body['name'])):
|
if not envs_api.VALID_NAME_REGEX.match(str(body['name'])):
|
||||||
msg = _('Environment Template must contain only alphanumeric '
|
msg = _('Environment Template must contain only alphanumeric '
|
||||||
'or "_-." characters, must start with alpha')
|
'or "_-." characters, must start with alpha')
|
||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
@ -114,7 +117,7 @@ class Controller(object):
|
|||||||
self._validate_request(request, env_template_id)
|
self._validate_request(request, env_template_id)
|
||||||
try:
|
try:
|
||||||
LOG.debug('ENV TEMP NAME: {0}>'.format(body['name']))
|
LOG.debug('ENV TEMP NAME: {0}>'.format(body['name']))
|
||||||
if not envs.VALID_NAME_REGEX.match(str(body['name'])):
|
if not envs_api.VALID_NAME_REGEX.match(str(body['name'])):
|
||||||
msg = _('Env Template must contain only alphanumeric '
|
msg = _('Env Template must contain only alphanumeric '
|
||||||
'or "_-." characters, must start with alpha')
|
'or "_-." characters, must start with alpha')
|
||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
@ -141,6 +144,68 @@ class Controller(object):
|
|||||||
env_temps.EnvTemplateServices.remove(env_template_id)
|
env_temps.EnvTemplateServices.remove(env_template_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def has_services(self, template):
|
||||||
|
""""It checks if the template has services
|
||||||
|
:param template: the template to check.
|
||||||
|
:return: True or False
|
||||||
|
"""
|
||||||
|
if not template.description:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if (template.description.get('services')):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
@request_statistics.stats_count(API_NAME, 'Create_environment')
|
||||||
|
def create_environment(self, request, env_template_id, body):
|
||||||
|
"""Creates environment and session from template.
|
||||||
|
:param request: operation request
|
||||||
|
:param env_template_id: environment template ID
|
||||||
|
:param body: the environment name
|
||||||
|
:return: session_id and environment_id
|
||||||
|
"""
|
||||||
|
LOG.debug('Templates:Create environment <Id: {0}>'.
|
||||||
|
format(env_template_id))
|
||||||
|
target = {"env_template_id": env_template_id}
|
||||||
|
policy.check('create_environment', request.context, target)
|
||||||
|
|
||||||
|
self._validate_request(request, env_template_id)
|
||||||
|
template = env_temps.EnvTemplateServices.\
|
||||||
|
get_env_template(env_template_id)
|
||||||
|
|
||||||
|
if ('name' not in body or
|
||||||
|
not envs_api.VALID_NAME_REGEX.match(str(body['name']))):
|
||||||
|
msg = _('Environment must contain only alphanumeric '
|
||||||
|
'or "_-." characters, must start with alpha')
|
||||||
|
LOG.error(msg)
|
||||||
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
LOG.debug('ENVIRONMENT NAME: {0}>'.format(body['name']))
|
||||||
|
|
||||||
|
try:
|
||||||
|
environment = envs.EnvironmentServices.create(
|
||||||
|
body.copy(), request.context.tenant)
|
||||||
|
except db_exc.DBDuplicateEntry:
|
||||||
|
msg = _('Environment with specified name already exists')
|
||||||
|
LOG.exception(msg)
|
||||||
|
raise exc.HTTPConflict(explanation=msg)
|
||||||
|
|
||||||
|
user_id = request.context.user
|
||||||
|
session = sessions.SessionServices.create(environment.id, user_id)
|
||||||
|
|
||||||
|
if self.has_services(template):
|
||||||
|
services_node = utils.TraverseHelper.get("services",
|
||||||
|
template.description)
|
||||||
|
utils.TraverseHelper.update("/Objects/services",
|
||||||
|
services_node,
|
||||||
|
environment.description)
|
||||||
|
|
||||||
|
envs.EnvironmentServices.save_environment_description(
|
||||||
|
session.id,
|
||||||
|
environment.description,
|
||||||
|
inner=False
|
||||||
|
)
|
||||||
|
return {"session_id": session.id, "environment_id": environment.id}
|
||||||
|
|
||||||
def _validate_request(self, request, env_template_id):
|
def _validate_request(self, request, env_template_id):
|
||||||
env_template_exists = env_temps.EnvTemplateServices.env_template_exist
|
env_template_exists = env_temps.EnvTemplateServices.env_template_exist
|
||||||
if not env_template_exists(env_template_id):
|
if not env_template_exists(env_template_id):
|
||||||
|
@ -27,7 +27,8 @@ class TestEnvTemplateApi(tb.ControllerTest, tb.MuranoApiTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestEnvTemplateApi, self).setUp()
|
super(TestEnvTemplateApi, self).setUp()
|
||||||
self.controller = templates.Controller()
|
self.controller = templates.Controller()
|
||||||
self.uuids = ['env_template_id']
|
self.uuids = ['env_template_id', 'other', 'network_id',
|
||||||
|
'environment_id', 'session_id']
|
||||||
self.mock_uuid = self._stub_uuid(self.uuids)
|
self.mock_uuid = self._stub_uuid(self.uuids)
|
||||||
|
|
||||||
def test_list_empty_env_templates(self):
|
def test_list_empty_env_templates(self):
|
||||||
@ -237,7 +238,7 @@ class TestEnvTemplateApi(tb.ControllerTest, tb.MuranoApiTestCase):
|
|||||||
"image": "cloud-fedora-v3",
|
"image": "cloud-fedora-v3",
|
||||||
"flavor": "m1.medium",
|
"flavor": "m1.medium",
|
||||||
"?": {
|
"?": {
|
||||||
"type": "io.murano.resources.LinuxMuranoInstance",
|
"type": "io.murano.resources.Linux",
|
||||||
"id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e"
|
"id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -261,7 +262,7 @@ class TestEnvTemplateApi(tb.ControllerTest, tb.MuranoApiTestCase):
|
|||||||
"image": "cloud-fedora-v3",
|
"image": "cloud-fedora-v3",
|
||||||
"flavor": "m1.medium",
|
"flavor": "m1.medium",
|
||||||
"?": {
|
"?": {
|
||||||
"type": "io.murano.resources.LinuxMuranoInstance",
|
"type": "io.murano.resources.Linux",
|
||||||
"id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e"
|
"id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -314,7 +315,7 @@ class TestEnvTemplateApi(tb.ControllerTest, tb.MuranoApiTestCase):
|
|||||||
"image": "cloud-fedora-v3",
|
"image": "cloud-fedora-v3",
|
||||||
"flavor": "m1.medium",
|
"flavor": "m1.medium",
|
||||||
"?": {
|
"?": {
|
||||||
"type": "io.murano.resources.LinuxMuranoInstance",
|
"type": "io.murano.resources.Linux",
|
||||||
"id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e"
|
"id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -418,3 +419,122 @@ class TestEnvTemplateApi(tb.ControllerTest, tb.MuranoApiTestCase):
|
|||||||
'/services/' + service_id)
|
'/services/' + service_id)
|
||||||
result = req.get_response(self.api)
|
result = req.get_response(self.api)
|
||||||
self.assertEqual(404, result.status_code)
|
self.assertEqual(404, result.status_code)
|
||||||
|
|
||||||
|
def test_create_environment(self):
|
||||||
|
"""Test that environment is created, session configured."""
|
||||||
|
self._set_policy_rules(
|
||||||
|
{'create_env_template': '@',
|
||||||
|
'create_environment': '@'}
|
||||||
|
)
|
||||||
|
|
||||||
|
self._create_env_template_no_service()
|
||||||
|
body_env = {'name': 'my_template'}
|
||||||
|
|
||||||
|
self.expect_policy_check('create_environment',
|
||||||
|
{'env_template_id': self.uuids[0]})
|
||||||
|
req = self._post('/templates/%s/create-environment' %
|
||||||
|
self.uuids[0], json.dumps(body_env))
|
||||||
|
session_result = req.get_response(self.api)
|
||||||
|
self.assertEqual(200, session_result.status_code)
|
||||||
|
self.assertIsNotNone(session_result)
|
||||||
|
body_returned = json.loads(session_result.body)
|
||||||
|
self.assertEqual(self.uuids[4], body_returned['session_id'])
|
||||||
|
self.assertEqual(self.uuids[3], body_returned['environment_id'])
|
||||||
|
|
||||||
|
def test_create_env_with_template_no_services(self):
|
||||||
|
"""Test that environment is created and session with template
|
||||||
|
without services.
|
||||||
|
"""
|
||||||
|
self._set_policy_rules(
|
||||||
|
{'create_env_template': '@',
|
||||||
|
'create_environment': '@'}
|
||||||
|
)
|
||||||
|
self._create_env_template_no_service()
|
||||||
|
|
||||||
|
self.expect_policy_check('create_environment',
|
||||||
|
{'env_template_id': self.uuids[0]})
|
||||||
|
body = {'name': 'my_template'}
|
||||||
|
|
||||||
|
req = self._post('/templates/%s/create-environment' %
|
||||||
|
self.uuids[0], json.dumps(body))
|
||||||
|
result = req.get_response(self.api)
|
||||||
|
self.assertIsNotNone(result)
|
||||||
|
self.assertEqual(200, result.status_code)
|
||||||
|
body_returned = json.loads(result.body)
|
||||||
|
self.assertEqual(self.uuids[4], body_returned['session_id'])
|
||||||
|
self.assertEqual(self.uuids[3], body_returned['environment_id'])
|
||||||
|
|
||||||
|
def test_mallformed_env_body(self):
|
||||||
|
"""Check that an illegal temp name results in an HTTPClientError."""
|
||||||
|
self._set_policy_rules(
|
||||||
|
{'create_env_template': '@',
|
||||||
|
'create_environment': '@'}
|
||||||
|
)
|
||||||
|
self. _create_env_template_no_service()
|
||||||
|
|
||||||
|
self.expect_policy_check('create_environment',
|
||||||
|
{'env_template_id': self.uuids[0]})
|
||||||
|
body = {'invalid': 'test'}
|
||||||
|
req = self._post('/templates/%s/create-environment' %
|
||||||
|
self.uuids[0], json.dumps(body))
|
||||||
|
result = req.get_response(self.api)
|
||||||
|
self.assertEqual(400, result.status_code)
|
||||||
|
|
||||||
|
def test_create_env_notexisting_templatebody(self):
|
||||||
|
"""Check that an illegal temp name results in an HTTPClientError."""
|
||||||
|
self._set_policy_rules(
|
||||||
|
{'create_environment': '@'}
|
||||||
|
)
|
||||||
|
env_template_id = 'noexisting'
|
||||||
|
self.expect_policy_check('create_environment',
|
||||||
|
{'env_template_id': env_template_id})
|
||||||
|
|
||||||
|
body = {'name': 'test'}
|
||||||
|
req = self._post('/templates/%s/create-environment'
|
||||||
|
% env_template_id, json.dumps(body))
|
||||||
|
result = req.get_response(self.api)
|
||||||
|
self.assertEqual(404, result.status_code)
|
||||||
|
|
||||||
|
def _create_env_template_no_service(self):
|
||||||
|
self.expect_policy_check('create_env_template')
|
||||||
|
fake_now = timeutils.utcnow()
|
||||||
|
timeutils.utcnow.override_time = fake_now
|
||||||
|
|
||||||
|
req = self._post('/templates', json.dumps({'name': 'name'}))
|
||||||
|
result = req.get_response(self.api)
|
||||||
|
self.assertEqual(200, result.status_code)
|
||||||
|
|
||||||
|
def _create_env_template_services(self):
|
||||||
|
fake_now = timeutils.utcnow()
|
||||||
|
timeutils.utcnow.override_time = fake_now
|
||||||
|
|
||||||
|
self.expect_policy_check('create_env_template')
|
||||||
|
|
||||||
|
fake_now = timeutils.utcnow()
|
||||||
|
timeutils.utcnow.override_time = fake_now
|
||||||
|
body = {
|
||||||
|
"name": "env_template_name",
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"instance": {
|
||||||
|
"assignFloatingIp": "true",
|
||||||
|
"keyname": "mykeyname",
|
||||||
|
"image": "cloud-fedora-v3",
|
||||||
|
"flavor": "m1.medium",
|
||||||
|
"?": {
|
||||||
|
"type": "io.murano.resources.Linux",
|
||||||
|
"id": "ef984a74-29a4-45c0-b1dc-2ab9f075732e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "orion",
|
||||||
|
"port": "8080",
|
||||||
|
"?": {
|
||||||
|
"type": "io.murano.apps.apache.Tomcat",
|
||||||
|
"id": "54cea43d-5970-4c73-b9ac-fea656f3c722"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
req = self._post('/templates', json.dumps(body))
|
||||||
|
req.get_response(self.api)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user