Merge "Add support for Docker image format"
This commit is contained in:
commit
8f5aaead07
@ -566,6 +566,7 @@ Default::
|
||||
('aki', _('AKI - Amazon Kernel Image')),
|
||||
('ami', _('AMI - Amazon Machine Image')),
|
||||
('ari', _('ARI - Amazon Ramdisk Image')),
|
||||
('docker', _('Docker')),
|
||||
('iso', _('ISO - Optical Disk Image')),
|
||||
('qcow2', _('QCOW2 - QEMU Emulator')),
|
||||
('raw', _('Raw')),
|
||||
|
@ -102,6 +102,10 @@ class IndexView(tables.DataTableView):
|
||||
LOG.warning(invalid_msg)
|
||||
except ValueError:
|
||||
LOG.warning(invalid_msg)
|
||||
elif (filter_field == 'disk_format' and
|
||||
filter_string.lower() == 'docker'):
|
||||
filters['disk_format'] = 'raw'
|
||||
filters['container_format'] = 'docker'
|
||||
else:
|
||||
filters[filter_field] = filter_string
|
||||
return filters
|
||||
|
@ -37,6 +37,49 @@ IMAGE_BACKEND_SETTINGS = getattr(settings, 'OPENSTACK_IMAGE_BACKEND', {})
|
||||
IMAGE_FORMAT_CHOICES = IMAGE_BACKEND_SETTINGS.get('image_formats', [])
|
||||
|
||||
|
||||
def create_image_metadata(data):
|
||||
"""Use the given dict of image form data to generate the metadata used for
|
||||
creating the image in glance.
|
||||
"""
|
||||
# Glance does not really do anything with container_format at the
|
||||
# moment. It requires it is set to the same disk_format for the three
|
||||
# Amazon image types, otherwise it just treats them as 'bare.' As such
|
||||
# we will just set that to be that here instead of bothering the user
|
||||
# with asking them for information we can already determine.
|
||||
disk_format = data['disk_format']
|
||||
if disk_format in ('ami', 'aki', 'ari',):
|
||||
container_format = disk_format
|
||||
elif disk_format == 'docker':
|
||||
# To support docker containers we allow the user to specify
|
||||
# 'docker' as the format. In that case we really want to use
|
||||
# 'raw' as the disk format and 'docker' as the container format.
|
||||
disk_format = 'raw'
|
||||
container_format = 'docker'
|
||||
else:
|
||||
container_format = 'bare'
|
||||
|
||||
# The Create form uses 'is_public' but the Update form uses 'public'. Just
|
||||
# being tolerant here so we don't break anything else.
|
||||
meta = {'is_public': data.get('is_public', data.get('public', False)),
|
||||
'protected': data['protected'],
|
||||
'disk_format': disk_format,
|
||||
'container_format': container_format,
|
||||
'min_disk': (data['minimum_disk'] or 0),
|
||||
'min_ram': (data['minimum_ram'] or 0),
|
||||
'name': data['name'],
|
||||
'properties': {}}
|
||||
|
||||
if data['description']:
|
||||
meta['properties']['description'] = data['description']
|
||||
if data.get('kernel'):
|
||||
meta['properties']['kernel_id'] = data['kernel']
|
||||
if data.get('ramdisk'):
|
||||
meta['properties']['ramdisk_id'] = data['ramdisk']
|
||||
if data.get('architecture'):
|
||||
meta['properties']['architecture'] = data['architecture']
|
||||
return meta
|
||||
|
||||
|
||||
class CreateImageForm(forms.SelfHandlingForm):
|
||||
name = forms.CharField(max_length=255, label=_("Name"))
|
||||
description = forms.CharField(max_length=255, label=_("Description"),
|
||||
@ -200,33 +243,9 @@ class CreateImageForm(forms.SelfHandlingForm):
|
||||
return data
|
||||
|
||||
def handle(self, request, data):
|
||||
# Glance does not really do anything with container_format at the
|
||||
# moment. It requires it is set to the same disk_format for the three
|
||||
# Amazon image types, otherwise it just treats them as 'bare.' As such
|
||||
# we will just set that to be that here instead of bothering the user
|
||||
# with asking them for information we can already determine.
|
||||
if data['disk_format'] in ('ami', 'aki', 'ari',):
|
||||
container_format = data['disk_format']
|
||||
else:
|
||||
container_format = 'bare'
|
||||
meta = create_image_metadata(data)
|
||||
|
||||
meta = {'is_public': data['is_public'],
|
||||
'protected': data['protected'],
|
||||
'disk_format': data['disk_format'],
|
||||
'container_format': container_format,
|
||||
'min_disk': (data['minimum_disk'] or 0),
|
||||
'min_ram': (data['minimum_ram'] or 0),
|
||||
'name': data['name'],
|
||||
'properties': {}}
|
||||
|
||||
if data['description']:
|
||||
meta['properties']['description'] = data['description']
|
||||
if data.get('kernel'):
|
||||
meta['properties']['kernel_id'] = data['kernel']
|
||||
if data.get('ramdisk'):
|
||||
meta['properties']['ramdisk_id'] = data['ramdisk']
|
||||
if data.get('architecture'):
|
||||
meta['properties']['architecture'] = data['architecture']
|
||||
# Add image source file or URL to metadata
|
||||
if (settings.HORIZON_IMAGES_ALLOW_UPLOAD and
|
||||
policy.check((("image", "upload_image"),), request) and
|
||||
data.get('image_file', None)):
|
||||
@ -240,7 +259,7 @@ class CreateImageForm(forms.SelfHandlingForm):
|
||||
image = api.glance.image_create(request, **meta)
|
||||
messages.success(request,
|
||||
_('Your image %s has been queued for creation.') %
|
||||
data['name'])
|
||||
meta['name'])
|
||||
return image
|
||||
except Exception as e:
|
||||
msg = _('Unable to create new image')
|
||||
@ -248,7 +267,7 @@ class CreateImageForm(forms.SelfHandlingForm):
|
||||
if hasattr(e, 'code') and e.code == 400:
|
||||
if "Invalid disk format" in e.details:
|
||||
msg = _('Unable to create new image: Invalid disk format '
|
||||
'%s for image.') % data['disk_format']
|
||||
'%s for image.') % meta['disk_format']
|
||||
elif "Image name too long" in e.details:
|
||||
msg = _('Unable to create new image: Image name too long.')
|
||||
|
||||
@ -313,26 +332,7 @@ class UpdateImageForm(forms.SelfHandlingForm):
|
||||
def handle(self, request, data):
|
||||
image_id = data['image_id']
|
||||
error_updating = _('Unable to update image "%s".')
|
||||
|
||||
if data['disk_format'] in ['aki', 'ari', 'ami']:
|
||||
container_format = data['disk_format']
|
||||
else:
|
||||
container_format = 'bare'
|
||||
|
||||
meta = {'is_public': data['public'],
|
||||
'protected': data['protected'],
|
||||
'disk_format': data['disk_format'],
|
||||
'container_format': container_format,
|
||||
'name': data['name'],
|
||||
'min_ram': (data['minimum_ram'] or 0),
|
||||
'min_disk': (data['minimum_disk'] or 0),
|
||||
'properties': {'description': data['description']}}
|
||||
if data.get('kernel'):
|
||||
meta['properties']['kernel_id'] = data['kernel']
|
||||
if data.get('ramdisk'):
|
||||
meta['properties']['ramdisk_id'] = data['ramdisk']
|
||||
if data.get('architecture'):
|
||||
meta['properties']['architecture'] = data['architecture']
|
||||
meta = create_image_metadata(data)
|
||||
# Ensure we do not delete properties that have already been
|
||||
# set on an image.
|
||||
meta['purge_props'] = False
|
||||
|
@ -222,9 +222,12 @@ def get_format(image):
|
||||
# which will raise an error if you call upper() on it.
|
||||
if not format:
|
||||
return format
|
||||
# Most image formats are untranslated acronyms, but raw is a word
|
||||
# and should be translated
|
||||
if format == "raw":
|
||||
if getattr(image, "container_format") == 'docker':
|
||||
return pgettext_lazy("Image format for display in table",
|
||||
u"Docker")
|
||||
# Most image formats are untranslated acronyms, but raw is a word
|
||||
# and should be translated
|
||||
return pgettext_lazy("Image format for display in table", u"Raw")
|
||||
return format.upper()
|
||||
|
||||
|
@ -81,6 +81,31 @@ class CreateImageFormTests(test.TestCase):
|
||||
source_type_dict = dict(form.fields['source_type'].choices)
|
||||
self.assertNotIn('file', source_type_dict)
|
||||
|
||||
def test_create_image_metadata_docker(self):
|
||||
form_data = {
|
||||
'name': u'Docker image',
|
||||
'description': u'Docker image test',
|
||||
'source_type': u'url',
|
||||
'image_url': u'/',
|
||||
'disk_format': u'docker',
|
||||
'architecture': u'x86-64',
|
||||
'minimum_disk': 15,
|
||||
'minimum_ram': 512,
|
||||
'is_public': False,
|
||||
'protected': False,
|
||||
'is_copying': False
|
||||
}
|
||||
meta = forms.create_image_metadata(form_data)
|
||||
self.assertEqual(meta['disk_format'], 'raw')
|
||||
self.assertEqual(meta['container_format'], 'docker')
|
||||
self.assertIn('properties', meta)
|
||||
self.assertNotIn('description', meta)
|
||||
self.assertNotIn('architecture', meta)
|
||||
self.assertEqual(meta['properties']['description'],
|
||||
form_data['description'])
|
||||
self.assertEqual(meta['properties']['architecture'],
|
||||
form_data['architecture'])
|
||||
|
||||
|
||||
class UpdateImageFormTests(test.TestCase):
|
||||
def test_is_format_field_editable(self):
|
||||
|
@ -79,17 +79,22 @@ class UpdateView(forms.ModalFormView):
|
||||
def get_initial(self):
|
||||
image = self.get_object()
|
||||
properties = getattr(image, 'properties', {})
|
||||
return {'image_id': self.kwargs['image_id'],
|
||||
data = {'image_id': self.kwargs['image_id'],
|
||||
'name': getattr(image, 'name', None) or image.id,
|
||||
'description': properties.get('description', ''),
|
||||
'kernel': properties.get('kernel_id', ''),
|
||||
'ramdisk': properties.get('ramdisk_id', ''),
|
||||
'architecture': properties.get('architecture', ''),
|
||||
'disk_format': getattr(image, 'disk_format', None),
|
||||
'minimum_ram': getattr(image, 'min_ram', None),
|
||||
'minimum_disk': getattr(image, 'min_disk', None),
|
||||
'public': getattr(image, 'is_public', None),
|
||||
'protected': getattr(image, 'protected', None)}
|
||||
disk_format = getattr(image, 'disk_format', None)
|
||||
if (disk_format == 'raw' and
|
||||
getattr(image, 'container_format') == 'docker'):
|
||||
disk_format = 'docker'
|
||||
data['disk_format'] = disk_format
|
||||
return data
|
||||
|
||||
|
||||
class DetailView(tabs.TabView):
|
||||
|
@ -265,6 +265,7 @@ OPENSTACK_NEUTRON_NETWORK = {
|
||||
# ('aki', _('AKI - Amazon Kernel Image')),
|
||||
# ('ami', _('AMI - Amazon Machine Image')),
|
||||
# ('ari', _('ARI - Amazon Ramdisk Image')),
|
||||
# ('docker', _('Docker')),
|
||||
# ('iso', _('ISO - Optical Disk Image')),
|
||||
# ('ova', _('OVA - Open Virtual Appliance')),
|
||||
# ('qcow2', _('QCOW2 - QEMU Emulator')),
|
||||
|
@ -81,6 +81,7 @@ OPENSTACK_IMAGE_BACKEND = {
|
||||
('aki', _('AKI - Amazon Kernel Image')),
|
||||
('ami', _('AMI - Amazon Machine Image')),
|
||||
('ari', _('ARI - Amazon Ramdisk Image')),
|
||||
('docker', _('Docker')),
|
||||
('iso', _('ISO - Optical Disk Image')),
|
||||
('ova', _('OVA - Open Virtual Appliance')),
|
||||
('qcow2', _('QCOW2 - QEMU Emulator')),
|
||||
|
Loading…
Reference in New Issue
Block a user