summaryrefslogtreecommitdiff
path: root/openstack_dashboard/dashboards
diff options
context:
space:
mode:
Diffstat (limited to 'openstack_dashboard/dashboards')
-rw-r--r--openstack_dashboard/dashboards/project/images/images/forms.py60
-rw-r--r--openstack_dashboard/dashboards/project/images/images/tables.py15
-rw-r--r--openstack_dashboard/dashboards/project/images/images/tests.py208
-rw-r--r--openstack_dashboard/dashboards/project/images/images/views.py4
-rw-r--r--openstack_dashboard/dashboards/project/images/templates/images/images/_create.html16
-rw-r--r--openstack_dashboard/dashboards/project/instances/tests.py163
-rw-r--r--openstack_dashboard/dashboards/project/volumes/volumes/tests.py9
7 files changed, 379 insertions, 96 deletions
diff --git a/openstack_dashboard/dashboards/project/images/images/forms.py b/openstack_dashboard/dashboards/project/images/images/forms.py
index 0105a116f..1c3a44999 100644
--- a/openstack_dashboard/dashboards/project/images/images/forms.py
+++ b/openstack_dashboard/dashboards/project/images/images/forms.py
@@ -65,25 +65,34 @@ def create_image_metadata(data):
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'],
+ meta = {'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 'description' in data:
- meta['properties']['description'] = data['description']
+ 'name': data['name']}
+
+ is_public = data.get('is_public', data.get('public', False))
+ properties = {}
+ # NOTE(tsufiev): in V2 the way how empty non-base attributes (AKA metadata)
+ # are handled has changed: in V2 empty metadata is kept in image
+ # properties, while in V1 they were omitted. Skip empty description (which
+ # is metadata) to keep the same behavior between V1 and V2
+ if data.get('description'):
+ properties['description'] = data['description']
if data.get('kernel'):
- meta['properties']['kernel_id'] = data['kernel']
+ properties['kernel_id'] = data['kernel']
if data.get('ramdisk'):
- meta['properties']['ramdisk_id'] = data['ramdisk']
+ properties['ramdisk_id'] = data['ramdisk']
if data.get('architecture'):
- meta['properties']['architecture'] = data['architecture']
+ properties['architecture'] = data['architecture']
+
+ if api.glance.VERSIONS.active < 2:
+ meta.update({'is_public': is_public, 'properties': properties})
+ else:
+ meta['visibility'] = 'public' if is_public else 'private'
+ meta.update(properties)
+
return meta
@@ -195,6 +204,24 @@ class CreateImageForm(CreateParent):
self._hide_file_source_type()
if not policy.check((("image", "set_image_location"),), request):
self._hide_url_source_type()
+
+ # GlanceV2 feature removals
+ if api.glance.VERSIONS.active >= 2:
+ # NOTE: GlanceV2 doesn't support copy-from feature, sorry!
+ self._hide_is_copying()
+ if not getattr(settings, 'IMAGES_ALLOW_LOCATION', False):
+ self._hide_url_source_type()
+ if (api.glance.get_image_upload_mode() == 'off' or not
+ policy.check((("image", "upload_image"),), request)):
+ # Neither setting a location nor uploading image data is
+ # allowed, so throw an error.
+ msg = _('The current Horizon settings indicate no valid '
+ 'image creation methods are available. Providing '
+ 'an image location and/or uploading from the '
+ 'local file system must be allowed to support '
+ 'image creation.')
+ messages.error(request, msg)
+ raise ValidationError(msg)
if not policy.check((("image", "publicize_image"),), request):
self._hide_is_public()
@@ -252,6 +279,10 @@ class CreateImageForm(CreateParent):
self.fields['is_public'].widget = HiddenInput()
self.fields['is_public'].initial = False
+ def _hide_is_copying(self):
+ self.fields['is_copying'].widget = HiddenInput()
+ self.fields['is_copying'].initial = False
+
def clean(self):
data = super(CreateImageForm, self).clean()
@@ -278,7 +309,7 @@ class CreateImageForm(CreateParent):
policy.check((("image", "upload_image"),), request) and
data.get('image_file', None)):
meta['data'] = data['image_file']
- elif data['is_copying']:
+ elif data.get('is_copying'):
meta['copy_from'] = data['image_url']
else:
meta['location'] = data['image_url']
@@ -369,9 +400,6 @@ class UpdateImageForm(forms.SelfHandlingForm):
image_id = data['image_id']
error_updating = _('Unable to update image "%s".')
meta = create_image_metadata(data)
- # Ensure we do not delete properties that have already been
- # set on an image.
- meta['purge_props'] = False
try:
image = api.glance.image_update(request, image_id, **meta)
diff --git a/openstack_dashboard/dashboards/project/images/images/tables.py b/openstack_dashboard/dashboards/project/images/images/tables.py
index df18973fd..e5e10b4fd 100644
--- a/openstack_dashboard/dashboards/project/images/images/tables.py
+++ b/openstack_dashboard/dashboards/project/images/images/tables.py
@@ -206,8 +206,14 @@ class OwnerFilter(tables.FixedFilterAction):
new_dict = button_dict.copy()
new_dict['value'] = new_dict['tenant']
buttons.append(new_dict)
- buttons.append(make_dict(_('Shared with Project'), 'shared',
- 'fa-share-square-o'))
+ # FIXME(bpokorny): Remove this check once admins can list images with
+ # GlanceV2 without getting all images in the whole cloud.
+ if api.glance.VERSIONS.active >= 2:
+ buttons.append(make_dict(_('Non-Public from Other Projects'),
+ 'other', 'fa-group'))
+ else:
+ buttons.append(make_dict(_('Shared with Project'), 'shared',
+ 'fa-share-square-o'))
buttons.append(make_dict(_('Public'), 'public', 'fa-group'))
return buttons
@@ -223,14 +229,15 @@ class OwnerFilter(tables.FixedFilterAction):
def get_image_categories(im, user_tenant_id):
categories = []
- if api.glance.is_image_public(im):
+ if im.is_public:
categories.append('public')
if im.owner == user_tenant_id:
categories.append('project')
elif im.owner in filter_tenant_ids():
categories.append(im.owner)
- elif not api.glance.is_image_public(im):
+ elif not im.is_public:
categories.append('shared')
+ categories.append('other')
return categories
diff --git a/openstack_dashboard/dashboards/project/images/images/tests.py b/openstack_dashboard/dashboards/project/images/images/tests.py
index ef1f336d5..df0e21699 100644
--- a/openstack_dashboard/dashboards/project/images/images/tests.py
+++ b/openstack_dashboard/dashboards/project/images/images/tests.py
@@ -38,7 +38,7 @@ from openstack_dashboard.dashboards.project.images.images import tables
IMAGES_INDEX_URL = reverse('horizon:project:images:index')
-class CreateImageFormTests(test.TestCase):
+class CreateImageFormTests(test.ResetImageAPIVersionMixin, test.TestCase):
@test.create_stubs({api.glance: ('image_list_detailed',)})
def test_no_location_or_file(self):
filters = {'disk_format': 'aki'}
@@ -64,6 +64,7 @@ class CreateImageFormTests(test.TestCase):
self.assertFalse(form.is_valid())
@override_settings(HORIZON_IMAGES_ALLOW_UPLOAD=False)
+ @override_settings(IMAGES_ALLOW_LOCATION=True)
@test.create_stubs({api.glance: ('image_list_detailed',)})
def test_image_upload_disabled(self):
filters = {'disk_format': 'aki'}
@@ -81,7 +82,8 @@ 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):
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_create_image_metadata_docker_v1(self):
form_data = {
'name': u'Docker image',
'description': u'Docker image test',
@@ -106,8 +108,29 @@ class CreateImageFormTests(test.TestCase):
self.assertEqual(meta['properties']['architecture'],
form_data['architecture'])
+ def test_create_image_metadata_docker_v2(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.assertNotIn('properties', meta)
+ self.assertEqual(meta['description'], form_data['description'])
+ self.assertEqual(meta['architecture'], form_data['architecture'])
+
-class UpdateImageFormTests(test.TestCase):
+class UpdateImageFormTests(test.ResetImageAPIVersionMixin, test.TestCase):
def test_is_format_field_editable(self):
form = forms.UpdateImageForm({})
disk_format = form.fields['disk_format']
@@ -127,8 +150,9 @@ class UpdateImageFormTests(test.TestCase):
self.assertEqual(res.context['image'].disk_format,
image.disk_format)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
@test.create_stubs({api.glance: ('image_update', 'image_get')})
- def test_image_update_post(self):
+ def test_image_update_post_v1(self):
image = self.images.first()
data = {
'name': u'Ubuntu 11.10',
@@ -156,10 +180,10 @@ class UpdateImageFormTests(test.TestCase):
name=data['name'],
min_ram=data['minimum_ram'],
min_disk=data['minimum_disk'],
- properties={'description': data['description'],
- 'architecture':
- data['architecture']},
- purge_props=False).AndReturn(image)
+ properties={
+ 'description': data['description'],
+ 'architecture':
+ data['architecture']}).AndReturn(image)
self.mox.ReplayAll()
url = reverse('horizon:project:images:images:update',
args=[image.id])
@@ -167,8 +191,47 @@ class UpdateImageFormTests(test.TestCase):
self.assertNoFormErrors(res)
self.assertEqual(res.status_code, 302)
+ @test.create_stubs({api.glance: ('image_update', 'image_get')})
+ def test_image_update_post_v2(self):
+ image = self.images.first()
+ data = {
+ 'name': u'Ubuntu 11.10',
+ 'image_id': str(image.id),
+ 'description': u'Login with admin/admin',
+ 'source_type': u'url',
+ 'image_url': u'http://cloud-images.ubuntu.com/releases/'
+ u'oneiric/release/ubuntu-11.10-server-cloudimg'
+ u'-amd64-disk1.img',
+ 'disk_format': u'qcow2',
+ 'architecture': u'x86-64',
+ 'minimum_disk': 15,
+ 'minimum_ram': 512,
+ 'is_public': False,
+ 'protected': False,
+ 'method': 'UpdateImageForm'}
+ api.glance.image_get(IsA(http.HttpRequest), str(image.id)) \
+ .AndReturn(image)
+ api.glance.image_update(IsA(http.HttpRequest),
+ image.id,
+ visibility='private',
+ protected=data['protected'],
+ disk_format=data['disk_format'],
+ container_format="bare",
+ name=data['name'],
+ min_ram=data['minimum_ram'],
+ min_disk=data['minimum_disk'],
+ description=data['description'],
+ architecture=data['architecture']).\
+ AndReturn(image)
+ self.mox.ReplayAll()
+ url = reverse('horizon:project:images:images:update',
+ args=[image.id])
+ res = self.client.post(url, data)
+ self.assertNoFormErrors(res)
+ self.assertEqual(res.status_code, 302)
-class ImageViewTests(test.TestCase):
+
+class ImageViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
@test.create_stubs({api.glance: ('image_list_detailed',)})
def test_image_create_get(self):
filters = {'disk_format': 'aki'}
@@ -186,8 +249,9 @@ class ImageViewTests(test.TestCase):
self.assertTemplateUsed(res,
'project/images/images/create.html')
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
@test.create_stubs({api.glance: ('image_create',)})
- def test_image_create_post_copy_from(self):
+ def test_image_create_post_copy_from_v1(self):
data = {
'source_type': u'url',
'image_url': u'http://cloud-images.ubuntu.com/releases/'
@@ -198,8 +262,9 @@ class ImageViewTests(test.TestCase):
api_data = {'copy_from': data['image_url']}
self._test_image_create(data, api_data)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
@test.create_stubs({api.glance: ('image_create',)})
- def test_image_create_post_location(self):
+ def test_image_create_post_location_v1(self):
data = {
'source_type': u'url',
'image_url': u'http://cloud-images.ubuntu.com/releases/'
@@ -210,8 +275,34 @@ class ImageViewTests(test.TestCase):
api_data = {'location': data['image_url']}
self._test_image_create(data, api_data)
+ @override_settings(IMAGES_ALLOW_LOCATION=True)
+ @test.create_stubs({api.glance: ('image_create',)})
+ def test_image_create_post_location_v2(self):
+ data = {
+ 'source_type': u'url',
+ 'image_url': u'http://cloud-images.ubuntu.com/releases/'
+ u'oneiric/release/ubuntu-11.10-server-cloudimg'
+ u'-amd64-disk1.img'}
+
+ api_data = {'location': data['image_url']}
+ self._test_image_create(data, api_data)
+
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ @test.create_stubs({api.glance: ('image_create',)})
+ def test_image_create_post_upload_v1(self):
+ temp_file = tempfile.NamedTemporaryFile()
+ temp_file.write(b'123')
+ temp_file.flush()
+ temp_file.seek(0)
+
+ data = {'source_type': u'file',
+ 'image_file': temp_file}
+
+ api_data = {'data': IsA(InMemoryUploadedFile)}
+ self._test_image_create(data, api_data)
+
@test.create_stubs({api.glance: ('image_create',)})
- def test_image_create_post_upload(self):
+ def test_image_create_post_upload_v2(self):
temp_file = tempfile.NamedTemporaryFile()
temp_file.write(b'123')
temp_file.flush()
@@ -223,8 +314,26 @@ class ImageViewTests(test.TestCase):
api_data = {'data': IsA(InMemoryUploadedFile)}
self._test_image_create(data, api_data)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
@test.create_stubs({api.glance: ('image_create',)})
- def test_image_create_post_with_kernel_ramdisk(self):
+ def test_image_create_post_with_kernel_ramdisk_v1(self):
+ temp_file = tempfile.NamedTemporaryFile()
+ temp_file.write(b'123')
+ temp_file.flush()
+ temp_file.seek(0)
+
+ data = {
+ 'source_type': u'file',
+ 'image_file': temp_file,
+ 'kernel_id': '007e7d55-fe1e-4c5c-bf08-44b4a496482e',
+ 'ramdisk_id': '007e7d55-fe1e-4c5c-bf08-44b4a496482a'
+ }
+
+ api_data = {'data': IsA(InMemoryUploadedFile)}
+ self._test_image_create(data, api_data)
+
+ @test.create_stubs({api.glance: ('image_create',)})
+ def test_image_create_post_with_kernel_ramdisk_v2(self):
temp_file = tempfile.NamedTemporaryFile()
temp_file.write(b'123')
temp_file.flush()
@@ -256,14 +365,22 @@ class ImageViewTests(test.TestCase):
api_data = {'container_format': 'bare',
'disk_format': data['disk_format'],
- 'is_public': True,
'protected': False,
'min_disk': data['minimum_disk'],
'min_ram': data['minimum_ram'],
- 'properties': {
- 'description': data['description'],
- 'architecture': data['architecture']},
'name': data['name']}
+ if api.glance.VERSIONS.active < 2:
+ api_data.update({'is_public': True,
+ 'properties': {
+ 'description': data['description'],
+ 'architecture': data['architecture']}
+ })
+ else:
+ api_data.update({'visibility': 'public',
+ 'description': data['description'],
+ 'architecture': data['architecture']
+ })
+
api_data.update(extra_api_data)
filters = {'disk_format': 'aki'}
@@ -286,12 +403,9 @@ class ImageViewTests(test.TestCase):
self.assertNoFormErrors(res)
self.assertEqual(res.status_code, 302)
- @test.create_stubs({api.glance: ('image_get',)})
- def test_image_detail_get(self):
- image = self.images.first()
-
+ def _test_image_detail_get(self, image):
api.glance.image_get(IsA(http.HttpRequest), str(image.id)) \
- .AndReturn(self.images.first())
+ .AndReturn(image)
self.mox.ReplayAll()
res = self.client.get(reverse('horizon:project:images:images:detail',
@@ -302,10 +416,20 @@ class ImageViewTests(test.TestCase):
self.assertEqual(res.context['image'].name, image.name)
self.assertEqual(res.context['image'].protected, image.protected)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
@test.create_stubs({api.glance: ('image_get',)})
- def test_image_detail_custom_props_get(self):
- image = self.images.list()[8]
+ def test_image_detail_get_v1(self):
+ image = self.images.first()
+ self._test_image_detail_get(image)
+
+ @test.create_stubs({api.glance: ('image_get',)})
+ def test_image_detail_get_v2(self):
+ image = self.imagesV2.first()
+
+ self._test_image_detail_get(image)
+
+ def _test_image_detail_custom_props_get(self, image):
api.glance.image_get(IsA(http.HttpRequest), str(image.id)) \
.AndReturn(image)
self.mox.ReplayAll()
@@ -320,8 +444,8 @@ class ImageViewTests(test.TestCase):
self.assertNotIn(('description'), image_keys)
# Test custom properties are sorted
- self.assertEqual(image_props[0], ('bar', 'bar', 'bar val'))
- self.assertEqual(image_props[1], ('foo', 'foo', 'foo val'))
+ self.assertLess(image_props.index(('bar', 'bar', 'bar val')),
+ image_props.index(('foo', 'foo', 'foo val')))
# Test all custom properties appear in template
self.assertContains(res, '<dt title="bar">bar</dt>')
@@ -329,10 +453,20 @@ class ImageViewTests(test.TestCase):
self.assertContains(res, '<dt title="foo">foo</dt>')
self.assertContains(res, '<dd>foo val</dd>')
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
@test.create_stubs({api.glance: ('image_get',)})
- def test_protected_image_detail_get(self):
- image = self.images.list()[2]
+ def test_image_detail_custom_props_get_v1(self):
+ image = self.images.list()[8]
+
+ self._test_image_detail_custom_props_get(image)
+
+ @test.create_stubs({api.glance: ('image_get',)})
+ def test_image_detail_custom_props_get_v2(self):
+ image = self.imagesV2.list()[2]
+ self._test_image_detail_custom_props_get(image)
+
+ def _test_protected_image_detail_get(self, image):
api.glance.image_get(IsA(http.HttpRequest), str(image.id)) \
.AndReturn(image)
self.mox.ReplayAll()
@@ -344,6 +478,19 @@ class ImageViewTests(test.TestCase):
'horizon/common/_detail.html')
self.assertEqual(res.context['image'].protected, image.protected)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ @test.create_stubs({api.glance: ('image_get',)})
+ def test_protected_image_detail_get_v1(self):
+ image = self.images.list()[2]
+
+ self._test_protected_image_detail_get(image)
+
+ @test.create_stubs({api.glance: ('image_get',)})
+ def test_protected_image_detail_get_v2(self):
+ image = self.imagesV2.list()[1]
+
+ self._test_protected_image_detail_get(image)
+
@test.create_stubs({api.glance: ('image_get',)})
def test_image_detail_get_with_exception(self):
image = self.images.first()
@@ -359,9 +506,8 @@ class ImageViewTests(test.TestCase):
@test.create_stubs({api.glance: ('image_get',)})
def test_image_update_get(self):
- image = self.images.first()
- image.disk_format = "ami"
- image.is_public = True
+ image = self.images.filter(is_public=True)[0]
+
api.glance.image_get(IsA(http.HttpRequest), str(image.id)) \
.AndReturn(image)
self.mox.ReplayAll()
diff --git a/openstack_dashboard/dashboards/project/images/images/views.py b/openstack_dashboard/dashboards/project/images/images/views.py
index 853a6ab7d..1fafc3871 100644
--- a/openstack_dashboard/dashboards/project/images/images/views.py
+++ b/openstack_dashboard/dashboards/project/images/images/views.py
@@ -19,6 +19,7 @@
"""
Views for managing images.
"""
+from django.conf import settings
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _
@@ -71,6 +72,9 @@ class CreateView(forms.ModalFormView):
context = super(CreateView, self).get_context_data(**kwargs)
upload_mode = api.glance.get_image_upload_mode()
context['image_upload_enabled'] = upload_mode != 'off'
+ context['images_allow_location'] = getattr(settings,
+ 'IMAGES_ALLOW_LOCATION',
+ False)
return context
diff --git a/openstack_dashboard/dashboards/project/images/templates/images/images/_create.html b/openstack_dashboard/dashboards/project/images/templates/images/images/_create.html
index e3c471a93..d9c425404 100644
--- a/openstack_dashboard/dashboards/project/images/templates/images/images/_create.html
+++ b/openstack_dashboard/dashboards/project/images/templates/images/images/_create.html
@@ -8,18 +8,22 @@
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>
- {% if image_upload_enabled %}
+ {% if image_upload_enabled and images_allow_location %}
{% trans "Images can be provided via an HTTP/HTTPS URL or be uploaded from your local file system." %}
+ {% elif image_upload_enabled %}
+ {% trans "Currently only images uploaded from your local file system are supported." %}
{% else %}
{% trans "Currently only images available via an HTTP/HTTPS URL are supported. The image location must be accessible to the Image Service." %}
{% endif %}
</p>
<p>
- <strong>{% trans "Please note: " %}</strong>
- {% if image_upload_enabled %}
- {% trans "If you select an image via an HTTP/HTTPS URL, the Image Location field MUST be a valid and direct URL to the image binary; it must also be accessible to the Image Service. URLs that redirect or serve error pages will result in unusable images." %}
- {% else %}
- {% trans "The Image Location field MUST be a valid and direct URL to the image binary. URLs that redirect or serve error pages will result in unusable images." %}
+ {% if images_allow_location %}
+ <strong>{% trans "Please note: " %}</strong>
+ {% if image_upload_enabled %}
+ {% trans "If you select an image via an HTTP/HTTPS URL, the Image Location field MUST be a valid and direct URL to the image binary; it must also be accessible to the Image Service. URLs that redirect or serve error pages will result in unusable images." %}
+ {% else %}
+ {% trans "The Image Location field MUST be a valid and direct URL to the image binary. URLs that redirect or serve error pages will result in unusable images." %}
+ {% endif %}
{% endif %}
</p>
{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/instances/tests.py b/openstack_dashboard/dashboards/project/instances/tests.py
index 6283f9059..8794499a5 100644
--- a/openstack_dashboard/dashboards/project/instances/tests.py
+++ b/openstack_dashboard/dashboards/project/instances/tests.py
@@ -28,6 +28,7 @@ from django.core.urlresolvers import reverse
from django.forms import widgets
from django import http
import django.test
+from django.test.utils import override_settings
from django.utils.http import urlencode
from mox3.mox import IgnoreArg # noqa
from mox3.mox import IsA # noqa
@@ -54,7 +55,14 @@ VOLUME_SEARCH_OPTS = dict(status=AVAILABLE, bootable=True)
SNAPSHOT_SEARCH_OPTS = dict(status=AVAILABLE)
-class InstanceTests(helpers.TestCase):
+class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
+ def setUp(self):
+ super(InstanceTests, self).setUp()
+ if api.glance.VERSIONS.active < 2:
+ self.versioned_images = self.images
+ else:
+ self.versioned_images = self.imagesV2
+
@helpers.create_stubs({
api.nova: (
'flavor_list',
@@ -1511,7 +1519,7 @@ class InstanceTests(helpers.TestCase):
config_drive=True,
config_drive_default=False,
test_with_profile=False):
- image = self.images.first()
+ image = self.versioned_images.first()
api.nova.extension_supported('BlockDeviceMappingV2Boot',
IsA(http.HttpRequest)) \
@@ -1525,7 +1533,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -1674,6 +1682,10 @@ class InstanceTests(helpers.TestCase):
self.assertEqual(step.action.initial['config_drive'],
config_drive_default)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_launch_instance_get_glance_v1(self):
+ self.test_launch_instance_get()
+
@django.test.utils.override_settings(
OPENSTACK_HYPERVISOR_FEATURES={'can_set_password': False})
def test_launch_instance_get_without_password(self):
@@ -1777,7 +1789,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -1853,6 +1865,10 @@ class InstanceTests(helpers.TestCase):
for volume in bootable_volumes:
self.assertIn(volume, volume_sources_ids)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_launch_instance_get_bootable_volumes_glance_v1(self):
+ self.test_launch_instance_get_bootable_volumes()
+
@helpers.update_settings(
OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'})
def test_launch_instance_get_bootable_volumes_with_profile(self):
@@ -1879,7 +1895,7 @@ class InstanceTests(helpers.TestCase):
test_with_profile=False,
test_with_multi_nics=False):
flavor = self.flavors.first()
- image = self.images.first()
+ image = self.versioned_images.first()
keypair = self.keypairs.first()
server = self.servers.first()
sec_group = self.security_groups.first()
@@ -1903,7 +1919,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -2024,6 +2040,10 @@ class InstanceTests(helpers.TestCase):
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_launch_instance_post_glance_v1(self):
+ self.test_launch_instance_post()
+
def test_launch_instance_post_no_disk_config_supported(self):
self.test_launch_instance_post(disk_config=False)
@@ -2046,7 +2066,7 @@ class InstanceTests(helpers.TestCase):
test_with_multi_nics=False,
):
flavor = self.flavors.first()
- image = self.images.first()
+ image = self.versioned_images.first()
keypair = self.keypairs.first()
server = self.servers.first()
sec_group = self.security_groups.first()
@@ -2068,7 +2088,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(IsA(http.HttpRequest),
filters={'is_public': True,
'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -2181,6 +2201,10 @@ class InstanceTests(helpers.TestCase):
def test_launch_instance_post_with_profile_and_port_error(self):
self._test_launch_instance_post_with_profile_and_port_error()
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_launch_instance_post_with_profile_and_port_error_glance_v1(self):
+ self.test_launch_instance_post_with_profile_and_port_error()
+
@helpers.update_settings(
OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'})
@helpers.create_stubs({api.glance: ('image_list_detailed',),
@@ -2263,7 +2287,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -2367,6 +2391,10 @@ class InstanceTests(helpers.TestCase):
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_launch_instance_post_boot_from_volume_glance_v1(self):
+ self.test_launch_instance_post_boot_from_volume()
+
def test_launch_instance_post_boot_from_volume_with_bdmv2(self):
self.test_launch_instance_post_boot_from_volume(test_with_bdmv2=True)
@@ -2422,7 +2450,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -2527,6 +2555,10 @@ class InstanceTests(helpers.TestCase):
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_lnch_inst_post_no_images_avail_boot_from_volume_glance_v1(self):
+ self.test_launch_instance_post_no_images_available_boot_from_volume()
+
@helpers.update_settings(
OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'})
def test_lnch_inst_post_no_images_avail_boot_from_vol_with_profile(self):
@@ -2712,7 +2744,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -2817,6 +2849,10 @@ class InstanceTests(helpers.TestCase):
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_launch_instance_post_boot_from_snapshot_glance_v1(self):
+ self.test_launch_instance_post_boot_from_snapshot()
+
def test_launch_instance_post_boot_from_snapshot_with_bdmv2(self):
self.test_launch_instance_post_boot_from_snapshot(test_with_bdmv2=True)
@@ -2945,7 +2981,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -3000,6 +3036,10 @@ class InstanceTests(helpers.TestCase):
self.assertTemplateUsed(res, views.WorkflowView.template_name)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_launch_flavorlist_error_glance_v1(self):
+ self.test_launch_flavorlist_error()
+
@helpers.update_settings(
OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'})
def test_launch_flavorlist_error_with_profile(self):
@@ -3024,7 +3064,7 @@ class InstanceTests(helpers.TestCase):
def test_launch_form_keystone_exception(self,
test_with_profile=False):
flavor = self.flavors.first()
- image = self.images.first()
+ image = self.versioned_images.first()
keypair = self.keypairs.first()
server = self.servers.first()
sec_group = self.security_groups.first()
@@ -3055,7 +3095,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -3151,6 +3191,10 @@ class InstanceTests(helpers.TestCase):
self.assertRedirectsNoFollow(res, INDEX_URL)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_launch_form_keystone_exception_with_profile_glance_v1(self):
+ self.test_launch_form_keystone_exception()
+
@helpers.update_settings(
OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'})
def test_launch_form_keystone_exception_with_profile(self):
@@ -3172,7 +3216,7 @@ class InstanceTests(helpers.TestCase):
def test_launch_form_instance_count_error(self,
test_with_profile=False):
flavor = self.flavors.first()
- image = self.images.first()
+ image = self.versioned_images.first()
keypair = self.keypairs.first()
server = self.servers.first()
volume = self.volumes.first()
@@ -3197,7 +3241,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -3273,6 +3317,10 @@ class InstanceTests(helpers.TestCase):
self.assertContains(res, "greater than or equal to 1")
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_launch_form_instance_count_error_glance_v1(self):
+ self.test_launch_form_instance_count_error()
+
@helpers.create_stubs({api.glance: ('image_list_detailed',),
api.neutron: ('network_list',
'profile_list',
@@ -3290,7 +3338,7 @@ class InstanceTests(helpers.TestCase):
def _test_launch_form_count_error(self, resource,
avail, test_with_profile=False):
flavor = self.flavors.first()
- image = self.images.first()
+ image = self.versioned_images.first()
keypair = self.keypairs.first()
server = self.servers.first()
volume = self.volumes.first()
@@ -3320,7 +3368,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -3407,7 +3455,11 @@ class InstanceTests(helpers.TestCase):
"512, Requested: 1024)" % {'avail': avail})
self.assertContains(res, msg)
- def test_launch_form_cores_count_error(self):
+ def test_launch_form_cores_count_error_glance_v2(self):
+ self._test_launch_form_count_error('cores', 1, test_with_profile=False)
+
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_launch_form_cores_count_error_glance_v1(self):
self._test_launch_form_count_error('cores', 1, test_with_profile=False)
def test_launch_form_ram_count_error(self):
@@ -3461,7 +3513,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -3547,18 +3599,22 @@ class InstanceTests(helpers.TestCase):
test_with_profile=False,
):
flavor = self.flavors.first()
- image = self.images.first()
+ image = self.versioned_images.first()
image.min_ram = flavor.ram
image.min_disk = flavor.disk + 1
self._test_launch_form_instance_requirement_error(image, flavor,
test_with_profile)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_launch_form_instance_requirement_error_disk_glance_v1(self):
+ self.test_launch_form_instance_requirement_error_disk()
+
def test_launch_form_instance_requirement_error_ram(
self,
test_with_profile=False,
):
flavor = self.flavors.first()
- image = self.images.first()
+ image = self.versioned_images.first()
image.min_ram = flavor.ram + 1
image.min_disk = flavor.disk
self._test_launch_form_instance_requirement_error(image, flavor,
@@ -3593,7 +3649,7 @@ class InstanceTests(helpers.TestCase):
widget_class,
widget_attrs):
flavor = self.flavors.first()
- image = self.images.first()
+ image = self.versioned_images.first()
keypair = self.keypairs.first()
server = self.servers.first()
volume = self.volumes.first()
@@ -3617,7 +3673,7 @@ class InstanceTests(helpers.TestCase):
IsA(http.HttpRequest),
filters={'is_public': True,
'status': 'active'}).AndReturn(
- [self.images.list(), False, False])
+ [self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -3692,8 +3748,8 @@ class InstanceTests(helpers.TestCase):
for widget_part in widget_content.split():
self.assertContains(res, widget_part)
- @django.test.utils.override_settings(
- OPENSTACK_HYPERVISOR_FEATURES={'can_set_mount_point': True})
+ @override_settings(
+ OPENSTACK_HYPERVISOR_FEATURES={'can_set_mount_point': True},)
def test_launch_form_instance_device_name_showed(self):
self._test_launch_form_instance_show_device_name(
u'vda', widgets.TextInput, {
@@ -3701,6 +3757,17 @@ class InstanceTests(helpers.TestCase):
'attrs': {'id': 'id_device_name'}}
)
+ @override_settings(
+ OPENSTACK_HYPERVISOR_FEATURES={'can_set_mount_point': True},
+ OPENSTACK_API_VERSIONS={'image': 1}
+ )
+ def test_launch_form_instance_device_name_showed_glance_v1(self):
+ self._test_launch_form_instance_show_device_name(
+ u'vda', widgets.TextInput, {
+ 'name': 'device_name', 'value': 'vda',
+ 'attrs': {'id': 'id_device_name'}}
+ )
+
@django.test.utils.override_settings(
OPENSTACK_HYPERVISOR_FEATURES={'can_set_mount_point': False})
def test_launch_form_instance_device_name_hidden(self):
@@ -3754,7 +3821,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -3834,22 +3901,26 @@ class InstanceTests(helpers.TestCase):
def test_launch_form_instance_volume_size_error(self,
test_with_profile=False):
- image = self.images.get(name='protected_images')
+ image = self.versioned_images.get(name='protected_images')
volume_size = image.min_disk // 2
msg = ("The Volume size is too small for the &#39;%s&#39; image" %
image.name)
self._test_launch_form_instance_volume_size(image, volume_size, msg,
test_with_profile)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_launch_form_instance_volume_size_error_glance_v1(self):
+ self.test_launch_form_instance_volume_size_error()
+
def test_launch_form_instance_non_int_volume_size(self,
test_with_profile=False):
- image = self.images.get(name='protected_images')
+ image = self.versioned_images.get(name='protected_images')
msg = "Enter a whole number."
self._test_launch_form_instance_volume_size(image, 1.5, msg,
test_with_profile)
def test_launch_form_instance_volume_exceed_quota(self):
- image = self.images.get(name='protected_images')
+ image = self.versioned_images.get(name='protected_images')
msg = "Requested volume exceeds quota: Available: 0, Requested: 1"
self._test_launch_form_instance_volume_size(image, image.min_disk,
msg, False, 0)
@@ -3975,7 +4046,7 @@ class InstanceTests(helpers.TestCase):
quotas: ('tenant_quota_usages',)})
def test_launch_with_empty_device_name_allowed(self):
flavor = self.flavors.get(name='m1.massive')
- image = self.images.first()
+ image = self.versioned_images.first()
keypair = self.keypairs.first()
server = self.servers.first()
sec_group = self.security_groups.first()
@@ -4007,7 +4078,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -4094,6 +4165,10 @@ class InstanceTests(helpers.TestCase):
res = self.client.post(url, form_data)
self.assertNoFormErrors(res)
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_launch_with_empty_device_name_allowed_glance_v1(self):
+ self.test_launch_with_empty_device_name_allowed()
+
@helpers.create_stubs({
api.nova: ('flavor_list', 'server_list', 'tenant_absolute_limits',
'extension_supported',),
@@ -4157,7 +4232,7 @@ class InstanceTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([self.versioned_images.list(), False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -4218,6 +4293,10 @@ class InstanceTests(helpers.TestCase):
html=True,
msg_prefix="The default key pair was not selected.")
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_select_default_keypair_if_only_one_glance_v1(self):
+ self.test_select_default_keypair_if_only_one()
+
@helpers.update_settings(
OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'})
def test_select_default_keypair_if_only_one_with_profile(self):
@@ -4945,7 +5024,7 @@ class InstanceAjaxTests(helpers.TestCase):
self.assertContains(res, "Not available")
-class ConsoleManagerTests(helpers.TestCase):
+class ConsoleManagerTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
def setup_consoles(self):
# Need to refresh with mocks or will fail since mox do not detect
@@ -5266,9 +5345,8 @@ class ConsoleManagerTests(helpers.TestCase):
cinder: ('volume_list',
'volume_snapshot_list',),
quotas: ('tenant_quota_usages',)})
- def test_port_cleanup_called_on_failed_vm_launch(self):
+ def _test_port_cleanup_called_on_failed_vm_launch(self, image, images):
flavor = self.flavors.first()
- image = self.images.first()
keypair = self.keypairs.first()
server = self.servers.first()
sec_group = self.security_groups.first()
@@ -5298,7 +5376,7 @@ class ConsoleManagerTests(helpers.TestCase):
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'is_public': True, 'status': 'active'}) \
- .AndReturn([self.images.list(), False, False])
+ .AndReturn([images, False, False])
api.glance.image_list_detailed(
IsA(http.HttpRequest),
filters={'property-owner_id': self.tenant.id,
@@ -5390,3 +5468,14 @@ class ConsoleManagerTests(helpers.TestCase):
res = self.client.post(url, form_data)
self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_port_cleanup_called_on_failed_vm_launch_v1(self):
+ image = self.images.first()
+ images = self.images.list()
+ self._test_port_cleanup_called_on_failed_vm_launch(image, images)
+
+ def test_port_cleanup_called_on_failed_vm_launch_v2(self):
+ image = self.imagesV2.first()
+ images = self.imagesV2.list()
+ self._test_port_cleanup_called_on_failed_vm_launch(image, images)
diff --git a/openstack_dashboard/dashboards/project/volumes/volumes/tests.py b/openstack_dashboard/dashboards/project/volumes/volumes/tests.py
index 778e88ba0..41b2ac060 100644
--- a/openstack_dashboard/dashboards/project/volumes/volumes/tests.py
+++ b/openstack_dashboard/dashboards/project/volumes/volumes/tests.py
@@ -40,7 +40,7 @@ VOLUME_VOLUMES_TAB_URL = urlunquote(reverse(
SEARCH_OPTS = dict(status=api.cinder.VOLUME_STATE_AVAILABLE)
-class VolumeViewTests(test.TestCase):
+class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
@test.create_stubs({cinder: ('volume_create',
'volume_snapshot_list',
'volume_type_list',
@@ -752,12 +752,17 @@ class VolumeViewTests(test.TestCase):
image.min_disk = 30
self._test_create_volume_from_image_under_image_min_disk_size(image)
- def test_create_volume_from_image_under_image_property_min_disk_size(self):
+ @override_settings(OPENSTACK_API_VERSIONS={'image': 1})
+ def test_create_volume_from_image_under_image_prop_min_disk_size_v1(self):
image = self.images.get(name="protected_images")
image.min_disk = 0
image.properties['min_disk'] = 30
self._test_create_volume_from_image_under_image_min_disk_size(image)
+ def test_create_volume_from_image_under_image_prop_min_disk_size_v2(self):
+ image = self.imagesV2.get(name="protected_images")
+ self._test_create_volume_from_image_under_image_min_disk_size(image)
+
@test.create_stubs({cinder: ('volume_snapshot_list',
'volume_type_list',
'volume_type_default',