diff --git a/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/launch-instance-model.service.js b/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/launch-instance-model.service.js index b246c5cef8..147b0a1204 100644 --- a/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/launch-instance-model.service.js +++ b/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/launch-instance-model.service.js @@ -564,7 +564,12 @@ if (enabledImage || enabledSnapshot) { var filter = {status: 'active', sort_key: 'name', sort_dir: 'asc'}; - glanceAPI.getImages(filter).then( + var filterCommunity = angular.merge({}, filter, {visibility: 'community'}); + var imagePromises = [ + glanceAPI.getImages(filter), + glanceAPI.getImages(filterCommunity) + ]; + $q.all(imagePromises).then( function(data) { onGetImageSources(data, enabledImage, enabledSnapshot); } @@ -670,13 +675,21 @@ model.imageSnapshots.length = 0; model.images.length = 0; - angular.forEach(data.data.items, function(image) { - if (isValidSnapshot(image) && enabledSnapshot) { - model.imageSnapshots.push(image); - } else if (isValidImage(image) && enabledImage) { - image.name_or_id = image.name || image.id; - model.images.push(image); - } + var imageIdsProcessed = []; + + angular.forEach(data, function(data) { + angular.forEach(data.data.items, function(image) { + if (imageIdsProcessed.includes(image.id)) { + return; + } + imageIdsProcessed.push(image.id); + if (isValidSnapshot(image) && enabledSnapshot) { + model.imageSnapshots.push(image); + } else if (isValidImage(image) && enabledImage) { + image.name_or_id = image.name || image.id; + model.images.push(image); + } + }); }); if (enabledImage) { diff --git a/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/launch-instance-model.service.spec.js b/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/launch-instance-model.service.spec.js index 21f34cd606..cc64988c91 100644 --- a/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/launch-instance-model.service.spec.js +++ b/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/launch-instance-model.service.spec.js @@ -130,19 +130,35 @@ beforeEach(module(function($provide) { $provide.value('horizon.app.core.openstack-service-api.glance', { - getImages: function () { - var images = [ - {container_format: 'aki', properties: {}}, - {container_format: 'ari', properties: {}}, - {container_format: 'ami', properties: {}, name: 'ami_image'}, - {container_format: 'raw', properties: {}, name: 'raw_image'}, - {container_format: 'ami', properties: {image_type: 'image'}, id: '1'}, - {container_format: 'raw', properties: {image_type: 'image'}, id: '2'}, - {container_format: 'ami', properties: { - block_device_mapping: '[{"source_type": "snapshot"}]'}}, - {container_format: 'raw', properties: { - block_device_mapping: '[{"source_type": "snapshot"}]'}} - ]; + getImages: function (params) { + var images; + if (params.visibility === 'community') { + images = [ + {id: '10', container_format: 'raw', properties: {image_type: 'image'}, + visibility: 'community'}, + // ID 6 is already returned by the first call (below), so this should be ignored. + // To clarify the difference, the content here is different intentionally. + {id: '6', container_format: 'raw', properties: {image_type: 'image'}, + visibility: 'community'}, + ]; + } else { + images = [ + // container_format aki and ari are not considered as bootable + {id: '1', container_format: 'aki', properties: {}}, + {id: '2', container_format: 'ari', properties: {}}, + // The following images are considered as "image" sources. + {id: '3', container_format: 'ami', properties: {}, name: 'ami_image'}, + {id: '4', container_format: 'raw', properties: {}, name: 'raw_image'}, + {id: '5', container_format: 'ami', properties: {image_type: 'image'}}, + {id: '6', container_format: 'raw', properties: {image_type: 'image'}}, + // The following images are considered as "snapshot" sources. + {id: '7', container_format: 'ami', + properties: {block_device_mapping: '[{"source_type": "snapshot"}]'}}, + {id: '8', container_format: 'raw', + properties: {block_device_mapping: '[{"source_type": "snapshot"}]'}}, + {id: '9', container_format: 'raw', properties: {image_type: 'snapshot'}}, + ]; + } var deferred = $q.defer(); deferred.resolve({data: {items: images}}); @@ -371,22 +387,23 @@ expect(model.newInstanceSpec).toBeDefined(); var expectedImages = [ - {container_format: 'ami', properties: {}, name: 'ami_image', name_or_id: 'ami_image'}, - {container_format: 'raw', properties: {}, name: 'raw_image', name_or_id: 'raw_image'}, - {container_format: 'ami', properties: {image_type: 'image'}, id: '1', name_or_id: '1'}, - {container_format: 'raw', properties: {image_type: 'image'}, id: '2', name_or_id: '2'} + {id: '3', container_format: 'ami', properties: {}, name: 'ami_image', + name_or_id: 'ami_image'}, + {id: '4', container_format: 'raw', properties: {}, name: 'raw_image', + name_or_id: 'raw_image'}, + {id: '5', container_format: 'ami', properties: {image_type: 'image'}, name_or_id: '5'}, + {id: '6', container_format: 'raw', properties: {image_type: 'image'}, name_or_id: '6'}, + {id: '10', container_format: 'raw', properties: {image_type: 'image'}, name_or_id: '10', + visibility: 'community'}, ]; expect(model.images).toEqual(expectedImages); var expectedSnapshots = [ - { - container_format: 'ami', - properties: {block_device_mapping: '[{"source_type": "snapshot"}]'} - }, - { - container_format: 'raw', - properties: {block_device_mapping: '[{"source_type": "snapshot"}]'} - } + {id: '7', container_format: 'ami', + properties: {block_device_mapping: '[{"source_type": "snapshot"}]'}}, + {id: '8', container_format: 'raw', + properties: {block_device_mapping: '[{"source_type": "snapshot"}]'}}, + {id: '9', container_format: 'raw', properties: {image_type: 'snapshot'}}, ]; expect(model.imageSnapshots).toEqual(expectedSnapshots);