Several fixes to Marked Images form

Added ability to filter Murano images by type

Change-Id: I142790b007cf7207ef6f1e23716c35d9c819e8b0
This commit is contained in:
Serg Melikyan 2013-10-10 16:33:48 +04:00
parent 116621a0a5
commit 9f7f3e660b
18 changed files with 158 additions and 125 deletions

View File

@ -13,15 +13,16 @@
# under the License.
import logging
import json
from django import forms
from django.utils.translation import ugettext_lazy as _
from horizon.forms import SelfHandlingForm
from horizon import messages, exceptions
from openstack_dashboard.api import glance
import json
from muranodashboard.panel.services import iterate_over_service_forms
from muranodashboard.panel.services import get_service_choices
from muranodashboard.panel.services import iterate_over_service_forms, \
get_service_choices
log = logging.getLogger(__name__)
@ -35,38 +36,42 @@ FORMS = [('service_choice', WizardFormServiceType)]
FORMS.extend(iterate_over_service_forms())
class AddImageForm(SelfHandlingForm):
title = forms.CharField(max_length="255",
label=_("Image Title"))
class MarkImageForm(SelfHandlingForm):
_metadata = {
'windows.2012': ' Windows Server 2012',
'cirros.demo': 'Murano Demo'
}
image_choices = forms.ChoiceField(label='Images')
windows_image = ('ws-2012-std', ' Windows Server 2012 Desktop')
demo_image = ('murano_demo', 'Murano Demo Image')
image_type = forms.ChoiceField(label="Murano Type",
choices=[windows_image, demo_image])
image = forms.ChoiceField(label='Image')
title = forms.CharField(max_length="255", label=_("Title"))
type = forms.ChoiceField(label="Type", choices=_metadata.items())
def __init__(self, request, *args, **kwargs):
super(AddImageForm, self).__init__(request, *args, **kwargs)
super(MarkImageForm, self).__init__(request, *args, **kwargs)
images = []
try:
images, _more = glance.image_list_detailed(request)
except Exception:
log.error("Failed to request image list from glance ")
images = []
exceptions.handle(request, _("Unable to retrieve public images."))
self.fields['image_choices'].choices = [(image.id, image.name)
for image in images]
log.error('Failed to request image list from Glance')
exceptions.handle(request, _('Unable to retrieve list of images'))
self.fields['image'].choices = [(i.id, i.name) for i in images]
def handle(self, request, data):
log.debug('Adding new murano using data {0}'.format(data))
murano_properties = {'murano_image_info': json.dumps(
{'title': data['title'], 'type': data['image_type']})}
try:
image = glance.image_update(request, data['image_choices'],
properties=murano_properties)
log.debug('Marking image with specified metadata: {0}'.format(data))
messages.success(request, _('Image added to Murano'))
return image
image_id = data['image']
properties = {
'murano_image_info': json.dumps({
'title': data['title'],
'type': data['type']
})
}
try:
img = glance.image_update(request, image_id, properties=properties)
messages.success(request, _('Image successfully marked'))
return img
except Exception:
exceptions.handle(request, _('Unable to update image.'))
exceptions.handle(request, _('Unable to mark image'))

View File

@ -212,6 +212,10 @@ class FlavorChoiceField(ChoiceField):
class ImageChoiceField(ChoiceField):
def __init__(self, *args, **kwargs):
self.image_type = kwargs.pop('image_type', None)
super(ImageChoiceField, self).__init__(*args, **kwargs)
@with_request
def update(self, request, **kwargs):
try:
@ -232,6 +236,18 @@ class ImageChoiceField(ChoiceField):
else:
title = murano_json.get('title', image.name)
murano_json['name'] = image.name
if self.image_type is not None:
itype = murano_json.get('type')
if not self.image_type and itype is None:
continue
prefix = '{type}.'.format(type=self.image_type)
if (not itype.startswith(prefix) and
not self.image_type == itype):
continue
image_mapping[smart_text(title)] = json.dumps(murano_json)
for name in sorted(image_mapping.keys()):

View File

@ -57,10 +57,10 @@ class CreateEnvironment(tables.LinkAction):
api.environment_create(request, environment)
class MuranoImages(tables.LinkAction):
class MarkedImages(tables.LinkAction):
name = 'show_images'
verbose_name = _('Murano Images')
url = 'horizon:project:murano:murano_images'
verbose_name = _('Marked Images')
url = 'horizon:project:murano:images'
def allowed(self, request, environment):
return True
@ -227,7 +227,7 @@ class EnvironmentsTable(tables.DataTable):
verbose_name = _('Environments')
row_class = UpdateEnvironmentRow
status_columns = ['status']
table_actions = (CreateEnvironment, MuranoImages)
table_actions = (CreateEnvironment, MarkedImages)
row_actions = (ShowEnvironmentServices, DeployEnvironment,
EditEnvironment, DeleteEnvironment, ShowDeployments)
@ -314,10 +314,10 @@ class EnvConfigTable(tables.DataTable):
verbose_name = _('Deployed Services')
class AddMuranoImage(tables.LinkAction):
name = "add_image"
verbose_name = _("Add Image")
url = "horizon:project:murano:add_image"
class MarkImage(tables.LinkAction):
name = "mark_image"
verbose_name = _("Mark Image")
url = "horizon:project:murano:mark_image"
classes = ("ajax-modal", "btn-create")
def allowed(self, request, image):
@ -325,26 +325,27 @@ class AddMuranoImage(tables.LinkAction):
class RemoveImageMetadata(tables.DeleteAction):
data_type_singular = _('Murano Metadata')
data_type_plural = _('Murano Metadatum')
data_type_singular = _('Metadata')
data_type_plural = _('Metadata')
def delete(self, request, obj_id):
try:
glance.image_update(request, obj_id, properties={})
messages.success(request, _('Image removed from Murano.'))
except Exception:
exceptions.handle(request, _('Unable to update image.'))
exceptions.handle(request, _('Unable to remove metadata'))
class ImagesTable(tables.DataTable):
image_title = tables.Column('title', verbose_name=_('Murano title'))
image_id = tables.Column('id', verbose_name=_('Image id'))
image_name = tables.Column('name', verbose_name=_('Name in Glance'))
image_type = tables.Column('name', verbose_name=_('Murano Type'))
class MarkedImagesTable(tables.DataTable):
image = tables.Column(
'name',
link='horizon:project:images_and_snapshots:images:detail',
verbose_name=_('Image')
)
type = tables.Column('type', verbose_name=_('Type'))
title = tables.Column('title', verbose_name=_('Title'))
class Meta:
name = 'images'
verbose_name = _('Murano Images')
table_actions = (AddMuranoImage, RemoveImageMetadata)
name = 'marked_images'
verbose_name = _('Marked Images')
table_actions = (MarkImage, RemoveImageMetadata)
row_actions = (RemoveImageMetadata,)

View File

@ -19,7 +19,7 @@ from views import Services
from views import CreateEnvironmentView
from views import DetailServiceView
from views import DeploymentsView
from views import MuranoImageView, AddMuranoImageView
from views import MarkedImagesView, MarkImageView
from views import Wizard, EditEnvironmentView
from forms import FORMS
from muranodashboard.panel.services import get_service_checkers
@ -40,14 +40,14 @@ urlpatterns = patterns(
url(r'^create_environment$', CreateEnvironmentView.as_view(),
name='create_environment'),
url(r'^murano_images$', MuranoImageView.as_view(),
name='murano_images'),
url(r'^images$', MarkedImagesView.as_view(),
name='images'),
url(r'^add_image$', AddMuranoImageView.as_view(),
name='add_image'),
url(r'^mark_image$', MarkImageView.as_view(),
name='mark_image'),
url(r'^remove_image$', MuranoImageView.as_view(),
name='remove_image'),
url(r'^remove_metadata$', MarkedImagesView.as_view(),
name='remove_metadata'),
url(ENVIRONMENT_ID + r'/update_environment$',
EditEnvironmentView.as_view(),

View File

@ -35,11 +35,11 @@ from tables import EnvironmentsTable
from tables import ServicesTable
from tables import DeploymentsTable
from tables import EnvConfigTable
from tables import ImagesTable
from tables import MarkedImagesTable
from workflows import CreateEnvironment, UpdateEnvironment
from tabs import ServicesTabs, DeploymentTabs
from forms import AddImageForm
from forms import MarkImageForm
from muranodashboard.panel import api
from muranoclient.common.exceptions import HTTPUnauthorized, \
@ -339,40 +339,40 @@ class DeploymentDetailsView(tabs.TabbedTableView):
**kwargs)
class MuranoImageView(tables.DataTableView):
table_class = ImagesTable
class MarkedImagesView(tables.DataTableView):
table_class = MarkedImagesTable
template_name = 'images/index.html'
def get_data(self):
images = []
try:
images, _more = glance.image_list_detailed(self.request)
except HTTPForbidden:
except Exception:
msg = _('Unable to retrieve list of images')
exceptions.handle(self.request, msg,
redirect=reverse("horizon:project:murano:index"))
murano_images = []
uri = reverse('horizon:project:murano:index')
exceptions.handle(self.request, msg, redirect=uri)
marked_images = []
for image in images:
murano_property = image.properties.get('murano_image_info')
if murano_property:
metadata = image.properties.get('murano_image_info')
if metadata:
try:
murano_json = json.loads(murano_property)
metadata = json.loads(metadata)
except ValueError:
LOG.warning("JSON in image metadata is not valid. "
"Check it in glance.")
messages.error(self.request,
_("Invalid murano image metadata"))
msg = _('Invalid metadata for image: {0}'.format(image.id))
LOG.warn(msg)
messages.error(self.request, msg)
else:
image.title = murano_json.get('title', 'No title')
image.type = murano_json.get('type', 'No title')
image.title = metadata.get('title', 'No Title')
image.type = metadata.get('type', 'No Type')
murano_images.append(image)
return murano_images
marked_images.append(image)
return marked_images
class AddMuranoImageView(ModalFormView):
form_class = AddImageForm
template_name = 'images/add.html'
class MarkImageView(ModalFormView):
form_class = MarkImageForm
template_name = 'images/mark.html'
context_object_name = 'image'
success_url = reverse_lazy("horizon:project:murano:murano_images")
success_url = reverse_lazy('horizon:project:murano:images')

View File

@ -115,6 +115,7 @@ forms:
required: false
- name: osImage
type: image
imageType: windows
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and

View File

@ -93,6 +93,7 @@ forms:
required: false
- name: osImage
type: image
imageType: windows
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and

View File

@ -118,6 +118,7 @@ forms:
required: false
- name: osImage
type: image
imageType: windows
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and

View File

@ -68,6 +68,7 @@ forms:
required: false
- name: osImage
type: image
imageType: cirros.demo
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and

View File

@ -208,6 +208,7 @@ forms:
required: false
- name: osImage
type: image
imageType: windows
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and

View File

@ -103,6 +103,7 @@ forms:
required: false
- name: osImage
type: image
imageType: windows
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and

View File

@ -84,6 +84,7 @@ forms:
required: false
- name: osImage
type: image
imageType: windows
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and

View File

@ -105,6 +105,7 @@ forms:
required: false
- name: osImage
type: image
imageType: windows
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and

View File

@ -1,32 +0,0 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block form_id %}add_murano_image_form{% endblock %}
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
{% block form_action %}add_image{% endblock %}
{% block modal-header %}{% trans "Add An Image" %}{% endblock %}
{% block modal-body %}
<div class="left">
<fieldset>
{% include "horizon/common/_form_fields.html" %}
</fieldset>
</div>
<div class="right">
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Add image to Murano. Valid image metadata will be added so this image can be picked during service creation." %}</p>
<p><strong>{% trans "Image Title" %}</strong>
{% blocktrans %}Enter an image desciption which will help you to recognize the service during service creation {% endblocktrans %}
</p>
<p><strong>{% trans "Images" %}</strong>
{% blocktrans %}Select image from Glance{% endblocktrans %}
</p>
<p><strong>{% trans "Murano Type" %}</strong>
{% blocktrans %}Pick image type from supported by Murano{% endblocktrans %}
</p>
</div>
{% endblock %}
{% block modal-footer %}
<input class="btn btn-primary pull-right" type="submit" value="{% trans "Update Image" %}" />
{% endblock %}

View File

@ -0,0 +1,35 @@
{% extends 'horizon/common/_modal_form.html' %}
{% load i18n %}
{% block form_id %}add_murano_image_form{% endblock %}
{% block form_attrs %}enctype='multipart/form-data'{% endblock %}
{% block form_action %}mark_image{% endblock %}
{% block modal-header %}{% trans 'Mark Image' %}{% endblock %}
{% block modal-body %}
<div class='left'>
<fieldset>
{% include 'horizon/common/_form_fields.html' %}
</fieldset>
</div>
<div class='right'>
<h3>{% trans 'Description:' %}</h3>
<p>{% trans 'Mark image with specific Murano metadata. Valid image metadata will be added to the selected image so image can be picked during service creation.' %}</p>
<p>
<strong>{% trans 'Image' %}:</strong>
{% blocktrans %}Select one of the images registered in the Glance{% endblocktrans %}
</p>
<p>
<strong>{% trans 'Title' %}:</strong>
{% blocktrans %}Image description which will help you to recognize the image during service creation{% endblocktrans %}
</p>
<p>
<strong>{% trans 'Type' %}:</strong>
{% blocktrans %}Pick image type from types supported by Murano{% endblocktrans %}
</p>
</div>
{% endblock %}
{% block modal-footer %}
<input class='btn btn-primary pull-right' type='submit' value='{% trans 'Mark' %}' />
{% endblock %}

View File

@ -1,11 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Add An Image" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Add Image To Murano") %}
{% endblock page_header %}
{% block main %}
{% include 'horizon/project/murano/images/_add.html' %}
{% endblock %}

View File

@ -1,9 +1,9 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Murano Images" %}{% endblock %}
{% block title %}{% trans "Marked Images" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Murano Images") %}
{% include "horizon/common/_page_header.html" with title=_("Marked Images") %}
{% endblock page_header %}
{% block main %}

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Mark Image" %}{% endblock %}
{% block page_header %}
{% include 'horizon/common/_page_header.html' with title=_('Mark image with Metadata') %}
{% endblock page_header %}
{% block main %}
{% include 'horizon/project/murano/images/_mark.html' %}
{% endblock %}