Murano-dashboard now shows warnings if glance v1 is unavailable

Murano-dashboard currently does not fully support glance v2. This commit
removes restriction to use murano-dashboard with v2-enabled horizon.
All the relevant places now attempt to create a v1 client instead of v2.
In case v1 is unavailable an error message is shown.

Co-authored-by: Kirill Zaitsev <k.zaitsev@me.com>

Closes-bug: #1624423
Change-Id: I4cbadd125043cdefd12aac02ec2035005f2a6bc9
This commit is contained in:
zhurong 2016-09-18 12:54:38 +08:00 committed by Kirill Zaitsev
parent 8da1613edc
commit a9dfbc4903
5 changed files with 129 additions and 91 deletions

View File

@ -100,14 +100,13 @@ class MarkImageForm(horizon_forms.SelfHandlingForm):
image_id = data['image'] image_id = data['image']
image_type = data['type'] if data['type'] != 'custom' else \ image_type = data['type'] if data['type'] != 'custom' else \
data['custom_type'] data['custom_type']
properties = glance.image_get(request, image_id).properties kwargs = {}
properties['murano_image_info'] = json.dumps({ kwargs['murano_image_info'] = json.dumps({
'title': data['title'], 'title': data['title'],
'type': image_type 'type': image_type
}) })
try: try:
img = glance.image_update(request, image_id, properties=properties) img = glance.image_update_properties(request, image_id, **kwargs)
messages.success(request, _('Image successfully marked')) messages.success(request, _('Image successfully marked'))
return img return img
except Exception: except Exception:

View File

@ -61,33 +61,47 @@ class MarkedImagesView(horizon_tables.DataTableView):
images = [] images = []
self._prev = False self._prev = False
self._more = False self._more = False
# TODO(kzaitsev) add v2 client support for marking images
try: try:
images_iter = glance.glanceclient(self.request).images.list( glance_v1_client = glance.glanceclient(self.request, "1")
**kwargs)
marked_images_iter = forms.filter_murano_images(
images_iter,
request=self.request)
images = list(itertools.islice(marked_images_iter, request_size))
# first and middle page condition
if len(images) > page_size:
images.pop(-1)
self._more = True
# middle page condition
if marker is not None:
self._prev = True
# first page condition when reached via prev back
elif sort_dir == 'asc' and marker is not None:
self._more = True
# last page condition
elif marker is not None:
self._prev = True
if prev_marker is not None:
images.reverse()
except Exception: except Exception:
msg = _('Unable to retrieve list of images') # Horizon seems to raise ImportError which doesn't look
uri = reverse('horizon:app-catalog:images:index') # specific enough. Let's catch any exceptions.
msg = _('Unable to create v1 glance client. Marking images '
'from murano-dashboard will be unavailable.')
uri = reverse('horizon:app-catalog:catalog:index')
exceptions.handle(self.request, msg, redirect=uri) exceptions.handle(self.request, msg, redirect=uri)
try:
images_iter = glance_v1_client.images.list(
**kwargs)
except Exception:
msg = _('Unable to retrieve list of images')
uri = reverse('horizon:app-catalog:catalog:index')
exceptions.handle(self.request, msg, redirect=uri)
marked_images_iter = forms.filter_murano_images(
images_iter,
request=self.request)
images = list(itertools.islice(marked_images_iter, request_size))
# first and middle page condition
if len(images) > page_size:
images.pop(-1)
self._more = True
# middle page condition
if marker is not None:
self._prev = True
# first page condition when reached via prev back
elif sort_dir == 'asc' and marker is not None:
self._more = True
# last page condition
elif marker is not None:
self._prev = True
if prev_marker is not None:
images.reverse()
return images return images

View File

@ -30,8 +30,3 @@ SESSION_ENGINE = 'django.contrib.sessions.backends.db'
# from openstack_dashboard.settings import POLICY_FILES # from openstack_dashboard.settings import POLICY_FILES
POLICY_FILES.update({'murano': 'murano_policy.json',}) POLICY_FILES.update({'murano': 'murano_policy.json',})
OPENSTACK_API_VERSIONS = {
"identity": 3,
"image": 1,
}

View File

@ -70,6 +70,61 @@ def is_app(wizard):
return False return False
def _ensure_images(name, package, request, step_data=None):
try:
glance_client = glance.glanceclient(
request, version='1')
except Exception:
glance_client = None
base_url = packages_consts.MURANO_REPO_URL
image_specs = package.images()
if not glance_client and len(image_specs):
# NOTE(kzaitsev): no glance_client. Probably v1 client
# is not available. Add warning, to let user know that
# we were unable to load images automagically
# since v2 does not have copy_from
download_urls = []
for image_spec in image_specs:
download_url = muranoclient_utils.to_url(
image_spec.get("Url", image_spec['Name']),
base_url=base_url,
path='images/',
)
download_urls.append(download_url)
msg = _("Couldn't initialise glance v1 client, "
"therefore could not download images for "
"'{0}' package. You may need to download them "
"manually from these locations: {1}").format(
name, ' '.join(download_urls))
messages.error(request, msg)
LOG.error(msg)
return
try:
imgs = muranoclient_utils.ensure_images(
glance_client=glance_client,
image_specs=package.images(),
base_url=base_url)
for img in imgs:
msg = _("Trying to add {0} image to glance. "
"Image will be ready for deployment after "
"successful upload").format(img['name'],)
messages.warning(request, msg)
log_msg = _("Trying to add {0}, {1} image to "
"glance. Image will be ready for "
"deployment after successful upload")\
.format(img['name'], img['id'],)
LOG.info(log_msg)
if step_data:
step_data['images'].append(img)
except Exception as e:
msg = _("Error {0} occurred while installing "
"images for {1}").format(e, name)
messages.error(request, msg)
LOG.exception(msg)
class PackageDefinitionsView(horizon_tables.DataTableView): class PackageDefinitionsView(horizon_tables.DataTableView):
table_class = tables.PackageDefinitionsTable table_class = tables.PackageDefinitionsTable
template_name = 'packages/index.html' template_name = 'packages/index.html'
@ -219,10 +274,7 @@ class ImportBundleWizard(horizon_views.PageTitleMixin, views.ModalFormMixin,
raise exceptions.Http302( raise exceptions.Http302(
reverse('horizon:app-catalog:packages:index')) reverse('horizon:app-catalog:packages:index'))
glance_client = glance.glanceclient(self.request, version='1')
for package_spec in bundle.package_specs(): for package_spec in bundle.package_specs():
try: try:
package = muranoclient_utils.Package.from_location( package = muranoclient_utils.Package.from_location(
package_spec['Name'], package_spec['Name'],
@ -240,26 +292,9 @@ class ImportBundleWizard(horizon_views.PageTitleMixin, views.ModalFormMixin,
reqs = package.requirements(base_url=base_url) reqs = package.requirements(base_url=base_url)
for dep_name, dep_package in six.iteritems(reqs): for dep_name, dep_package in six.iteritems(reqs):
try: _ensure_images(dep_name, dep_package,
imgs = muranoclient_utils.ensure_images( self.request)
glance_client=glance_client,
image_specs=dep_package.images(),
base_url=base_url)
for img in imgs:
msg = _("Trying to add {0} image to glance. "
"Image will be ready for deployment after"
" successful upload").format(img['name'],)
messages.warning(self.request, msg)
log_msg = _("Trying to add {0}, {1} image to "
"glance. Image will be ready for "
"deployment after successful upload")\
.format(img['name'], img['id'],)
LOG.info(log_msg)
except Exception as e:
msg = _("Error {0} occurred while installing "
"images for {1}").format(e, dep_name)
messages.error(self.request, msg)
LOG.exception(msg)
try: try:
files = {dep_name: dep_package.file()} files = {dep_name: dep_package.file()}
package = api.muranoclient( package = api.muranoclient(
@ -354,16 +389,29 @@ class ImportPackageWizard(horizon_views.PageTitleMixin, views.ModalFormMixin,
# Images have been imported as private images during the 'upload' step # Images have been imported as private images during the 'upload' step
# If the package is public, make the required images public # If the package is public, make the required images public
if data['is_public']: if data['is_public']:
glance_client = glance.glanceclient(self.request, version='1') try:
for img in installed_images: glance_client = glance.glanceclient(self.request, '1')
try: except Exception:
glance_client.images.update(img['id'], is_public=True) glance_client = None
LOG.debug('Success update for image {0}'.format(img['id']))
except Exception as e: if glance_client:
msg = _("Error {0} occurred while setting image {1}, {2} " for img in installed_images:
"public").format(e, img['name'], img['id']) try:
messages.error(self.request, msg) glance_client.images.update(img['id'], is_public=True)
LOG.exception(msg) LOG.debug(
'Success update for image {0}'.format(img['id']))
except Exception as e:
msg = _("Error {0} occurred while setting image {1}, "
"{2} public").format(e, img['name'], img['id'])
messages.error(self.request, msg)
LOG.exception(msg)
elif len(installed_images):
msg = _("Couldn't initialise glance v1 client, "
"therefore could not make the following images "
"public: {0}").format(' '.join(
[img['name'] for img in installed_images]))
messages.warning(self.request, msg)
LOG.warning(msg)
try: try:
data['tags'] = [t.strip() for t in data['tags'].split(',')] data['tags'] = [t.strip() for t in data['tags'].split(',')]
@ -447,36 +495,13 @@ class ImportPackageWizard(horizon_views.PageTitleMixin, views.ModalFormMixin,
raise exceptions.Http302( raise exceptions.Http302(
reverse('horizon:app-catalog:packages:index')) reverse('horizon:app-catalog:packages:index'))
def _ensure_images(name, package):
try:
imgs = muranoclient_utils.ensure_images(
glance_client=glance_client,
image_specs=package.images(),
base_url=base_url)
for img in imgs:
msg = _("Trying to add {0} image to glance. "
"Image will be ready for deployment after "
"successful upload").format(img['name'],)
messages.warning(self.request, msg)
log_msg = _("Trying to add {0}, {1} image to "
"glance. Image will be ready for "
"deployment after successful upload")\
.format(img['name'], img['id'],)
LOG.info(log_msg)
step_data['images'].append(img)
except Exception as e:
msg = _("Error {0} occurred while installing "
"images for {1}").format(e, name)
messages.error(self.request, msg)
LOG.exception(msg)
reqs = package.requirements(base_url=base_url) reqs = package.requirements(base_url=base_url)
glance_client = glance.glanceclient(self.request, version='1')
original_package = reqs.pop(name) original_package = reqs.pop(name)
step_data['dependencies'] = [] step_data['dependencies'] = []
step_data['images'] = [] step_data['images'] = []
for dep_name, dep_package in six.iteritems(reqs): for dep_name, dep_package in six.iteritems(reqs):
_ensure_images(dep_name, dep_package) _ensure_images(dep_name, dep_package, self.request, step_data)
try: try:
files = {dep_name: dep_package.file()} files = {dep_name: dep_package.file()}
package = api.muranoclient(self.request).packages.create( package = api.muranoclient(self.request).packages.create(
@ -501,7 +526,7 @@ class ImportPackageWizard(horizon_views.PageTitleMixin, views.ModalFormMixin,
continue continue
# add main packages images # add main packages images
_ensure_images(name, original_package) _ensure_images(name, original_package, self.request, step_data)
# import main package itself # import main package itself
try: try:

View File

@ -0,0 +1,5 @@
---
other:
- Murano Dashboard relies on Glance v1 API for image uploads.
In case it is not available an error will be shown and all the
image-related functionality will be unavailable.