From 28586897671e3aa2d9abcfb40e78d345436bc8a7 Mon Sep 17 00:00:00 2001 From: Alexander Tivelkov Date: Tue, 5 Apr 2016 19:04:27 +0300 Subject: [PATCH] 'GetPackageUI' API can now be called even if Glare is used Since Glare support was introduced the 'catalog/packages' part of Murano API (/v1/catalog/packages) became obsolete and was intended to be used for "legacy" (i.e. non-glare-based) package storage. The murano client was supposed to directly call glare to retrieve the packages. However, the "GetPackageUI" call (GET /v1/catalog/packages/%pkg_id%/ui) is different: not all the packages bundle the UI definitions, some require Murano to generate them based on the contents of the package. This is true for HOT-based packages and others, plugin-based ones. In future this will be true for 100% of the packages when the dynamic ui and object model generation is added. Because of this that API should be callable even if Glare is configured as a package storage backend. It should fetch the artifact from glare, unpack it and use whatever plugin-specific logic required to generate the UI definitions for this particular package. This patch introduces appropriate change while maintaining the backwards compatibility: in the legacy mode (i.e. when murano's DB acts as package storage) the UI is read directly from an appropriate DB table without fetching the whole package. This fixes the issue when the HOT-based packages could not be deplpoyed properly with murano-dashboard, but the murano-client has to be updated as well to properly call the modified API even if Glare is enabled. Change-Id: Id9327e4015e1c0a1553c0b1a0151a94ee4da2928 Partial-bug: #1565805 --- murano/api/middleware/context.py | 4 ++ murano/api/v1/catalog.py | 53 +++++++++++++++++-- murano/context.py | 5 +- ...enable-hot-for-glare-8026f2dccad1732e.yaml | 6 +++ 4 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 releasenotes/notes/enable-hot-for-glare-8026f2dccad1732e.yaml diff --git a/murano/api/middleware/context.py b/murano/api/middleware/context.py index 143f3c082..d6704105d 100644 --- a/murano/api/middleware/context.py +++ b/murano/api/middleware/context.py @@ -14,6 +14,7 @@ from oslo_config import cfg from oslo_middleware import request_id as oslo_request_id +from oslo_serialization import jsonutils from murano.common.i18n import _ from murano.common import wsgi @@ -50,6 +51,9 @@ class ContextMiddleware(wsgi.Middleware): 'request_id': req.environ.get(oslo_request_id.ENV_REQUEST_ID), 'roles': roles } + sc_header = req.headers.get('X-Service-Catalog') + if sc_header: + kwargs['service_catalog'] = jsonutils.loads(sc_header) req.context = murano.context.RequestContext(**kwargs) @classmethod diff --git a/murano/api/v1/catalog.py b/murano/api/v1/catalog.py index b4057efdb..392e485bb 100644 --- a/murano/api/v1/catalog.py +++ b/murano/api/v1/catalog.py @@ -18,6 +18,8 @@ import os import tempfile import jsonschema +from keystoneclient import exceptions as keystone_ex +from keystoneclient import service_catalog from oslo_config import cfg from oslo_db import exception as db_exc from oslo_log import log as logging @@ -34,6 +36,7 @@ from murano.db.catalog import api as db_api from murano.common.i18n import _, _LW from murano.packages import exceptions as pkg_exc from murano.packages import load_utils +from muranoclient.glance import client as glare_client LOG = logging.getLogger(__name__) @@ -266,11 +269,21 @@ class Controller(object): os.remove(tempf.name) def get_ui(self, req, package_id): - target = {'package_id': package_id} - policy.check("get_package", req.context, target) + if CONF.engine.packages_service == 'murano': + target = {'package_id': package_id} + policy.check("get_package", req.context, target) - package = db_api.package_get(package_id, req.context) - return package.ui_definition + package = db_api.package_get(package_id, req.context) + return package.ui_definition + else: + g_client = self._get_glare_client(req) + blob_data = g_client.artifacts.download_blob(package_id, 'archive') + with tempfile.NamedTemporaryFile() as tempf: + for chunk in blob_data: + tempf.write(chunk) + with load_utils.load_from_file(tempf.name, target_dir=None, + drop_dir=True) as pkg: + return pkg.ui def get_logo(self, req, package_id): target = {'package_id': package_id} @@ -392,6 +405,38 @@ class Controller(object): raise exc.HTTPForbidden(explanation=msg) db_api.category_delete(category_id) + def _get_glare_client(self, request): + glare_settings = CONF.glare + token = request.context.auth_token + url = glare_settings.url + if not url: + self._get_glare_url(request) + client = glare_client.Client( + endpoint=url, token=token, insecure=glare_settings.insecure, + key_file=glare_settings.key_file or None, + ca_file=glare_settings.ca_file or None, + cert_file=glare_settings.cert_file or None, + type_name='murano', + type_version=1) + return client + + def _get_glare_url(self, request): + sc = request.context.service_catalog + token = request.context.auth_token + try: + return service_catalog.ServiceCatalogV2( + {'serviceCatalog': sc}).url_for( + service_type='artifact', + endpoint_type=CONF.glare.endpoint_type, + region_name=CONF.home_region) + except keystone_ex.EndpointNotFound: + return service_catalog.ServiceCatalogV3( + token, + {'catalog': sc}).url_for( + service_type='artifact', + endpoint_type=CONF.glare.endpoint_type, + region_name=CONF.home_region) + def create_resource(): specific_content_types = { diff --git a/murano/context.py b/murano/context.py index 16e6d421d..6f208ca3d 100644 --- a/murano/context.py +++ b/murano/context.py @@ -25,11 +25,12 @@ class RequestContext(context.RequestContext): """ def __init__(self, session=None, - roles=None, is_admin=None, + roles=None, is_admin=None, service_catalog=None, **kwargs): super(RequestContext, self).__init__(**kwargs) self.session = session - + self.roles = roles or [] + self.service_catalog = service_catalog self.is_admin = is_admin if self.is_admin is None: self.is_admin = policy.check_is_admin(self) diff --git a/releasenotes/notes/enable-hot-for-glare-8026f2dccad1732e.yaml b/releasenotes/notes/enable-hot-for-glare-8026f2dccad1732e.yaml new file mode 100644 index 000000000..443cc8a73 --- /dev/null +++ b/releasenotes/notes/enable-hot-for-glare-8026f2dccad1732e.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - Fixed a bug when the UI dialog was not displayed in Murano Dashboard for + applications which don't have UI definitions bundled in the package but + generate them based on the package contents instead. This usually affected + HOT-based packages and other non-muranopl-based applications.