diff --git a/doc/source/topics/settings.rst b/doc/source/topics/settings.rst index 64cd3ea19f..e598a30469 100644 --- a/doc/source/topics/settings.rst +++ b/doc/source/topics/settings.rst @@ -432,7 +432,8 @@ This example sorts flavors by vcpus in descending order:: Default:: { - 'images_panel': True + 'images_panel': True, + 'flavors_panel': False, } A dictionary of currently available AngularJS features. This allows simple diff --git a/openstack_dashboard/dashboards/admin/flavors/urls.py b/openstack_dashboard/dashboards/admin/flavors/urls.py index 4f044b483c..6739aa50a2 100644 --- a/openstack_dashboard/dashboards/admin/flavors/urls.py +++ b/openstack_dashboard/dashboards/admin/flavors/urls.py @@ -16,13 +16,24 @@ # License for the specific language governing permissions and limitations # under the License. +from django.conf import settings from django.conf.urls import url from openstack_dashboard.dashboards.admin.flavors import views -urlpatterns = [ - url(r'^$', views.IndexView.as_view(), name='index'), - url(r'^create/$', views.CreateView.as_view(), name='create'), - url(r'^(?P[^/]+)/update/$', views.UpdateView.as_view(), name='update'), -] +if settings.ANGULAR_FEATURES['flavors_panel']: + # New angular panel + urlpatterns = [ + url(r'^$', views.AngularIndexView.as_view(), name='index'), + url(r'^create/$', views.AngularIndexView.as_view(), name='create'), + url(r'^(?P[^/]+)/update/$', views.AngularIndexView.as_view(), + name='index'), + ] +else: + urlpatterns = [ + url(r'^$', views.IndexView.as_view(), name='index'), + url(r'^create/$', views.CreateView.as_view(), name='create'), + url(r'^(?P[^/]+)/update/$', + views.UpdateView.as_view(), name='update'), + ] diff --git a/openstack_dashboard/dashboards/admin/flavors/views.py b/openstack_dashboard/dashboards/admin/flavors/views.py index 0bfc44ed5c..a4322ce307 100644 --- a/openstack_dashboard/dashboards/admin/flavors/views.py +++ b/openstack_dashboard/dashboards/admin/flavors/views.py @@ -18,6 +18,7 @@ from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ +from django.views import generic from horizon import exceptions from horizon import tables @@ -34,6 +35,10 @@ from openstack_dashboard.dashboards.admin.flavors \ INDEX_URL = "horizon:admin:flavors:index" +class AngularIndexView(generic.TemplateView): + template_name = 'angular.html' + + class IndexView(tables.DataTableView): table_class = project_tables.FlavorsTable template_name = 'admin/flavors/index.html' diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/admin.module.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/admin.module.js deleted file mode 100644 index b068dca036..0000000000 --- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/admin.module.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -(function() { - 'use strict'; - - /** - * @ngdoc horizon.dashboard.admin - * @ngModule - * - * @description - * Dashboard module to host various admin panels. - */ - angular - .module('horizon.dashboard.admin', [ - 'horizon.dashboard.admin.flavors' - ]) - .config(config); - - config.$inject = [ - '$provide', - '$windowProvider' - ]; - - /** - * @name horizon.dashboard.admin.basePath - * @description Base path for the admin dashboard - */ - function config($provide, $windowProvider) { - var path = $windowProvider.$get().STATIC_URL + 'dashboard/admin/'; - $provide.constant('horizon.dashboard.admin.basePath', path); - } - -})(); diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/admin.module.spec.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/admin.module.spec.js deleted file mode 100644 index d9ca3f6df4..0000000000 --- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/admin.module.spec.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -(function() { - 'use strict'; - - describe('horizon.dashboard.admin', function() { - var staticUrl, basePath; - - beforeEach(module('horizon.dashboard.admin')); - - beforeEach(inject(function($injector) { - staticUrl = $injector.get('$window').STATIC_URL; - basePath = $injector.get('horizon.dashboard.admin.basePath'); - })); - - it('should exist', function() { - expect(angular.module('horizon.dashboard.admin')).toBeDefined(); - }); - - it('should set path properly', function () { - expect(basePath).toEqual(staticUrl + 'dashboard/admin/'); - }); - - }); - -})(); diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/filters/has-extras.filter.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/filters/has-extras.filter.js deleted file mode 100644 index 80017bb6e6..0000000000 --- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/filters/has-extras.filter.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -(function () { - 'use strict'; - - angular - .module('horizon.dashboard.admin.flavors') - .filter('hasExtras', hasExtrasFilter); - - hasExtrasFilter.$inject = []; - - /** - * @ngdoc filter - * @name hasExtrasFilter - * @description - * If input is defined and has more than one property return 'Yes' else return 'No' - * - */ - function hasExtrasFilter() { - return function check(input) { - if (input && - angular.isObject(input) && - !angular.isArray(input) && - Object.keys(input).length > 0) { - return true; - } - - return false; - }; - } - -})(); diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/filters/has-extras.filter.spec.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/filters/has-extras.filter.spec.js deleted file mode 100644 index 6c53f4125e..0000000000 --- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/filters/has-extras.filter.spec.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -(function() { - 'use strict'; - - describe('horizon.dashboard.admin.flavors.hasExtras', function() { - - var hasExtras; - - beforeEach(module('horizon.framework.util.i18n')); - beforeEach(module('horizon.dashboard.admin.flavors')); - - beforeEach(inject(function(_hasExtrasFilter_) { - hasExtras = _hasExtrasFilter_; - })); - - it('returns Yes when key is present', function() { - var input = { 1: 'test' }; - expect(hasExtras(input)).toBeTruthy(); - }); - - it('returns No when object is undefined or has no properties', function() { - expect(hasExtras()).not.toBeTruthy(); - expect(hasExtras({})).not.toBeTruthy(); - expect(hasExtras('string')).not.toBeTruthy(); - expect(hasExtras(1)).not.toBeTruthy(); - expect(hasExtras([1])).not.toBeTruthy(); - }); - }); - -})(); diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/flavors.module.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/flavors.module.js deleted file mode 100644 index 2f1f106745..0000000000 --- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/flavors.module.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -(function() { - 'use strict'; - - /** - * @ngdoc horizon.dashboard.admin.flavors - * @ngModule - * - * @description - * Provides all of the services and widgets required - * to support and display the flavors panel. - */ - angular - .module('horizon.dashboard.admin.flavors', []); - -})(); diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/flavors.module.spec.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/flavors.module.spec.js deleted file mode 100644 index 5a35e76c5f..0000000000 --- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/flavors.module.spec.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -(function () { - 'use strict'; - - describe('horizon.dashboard.admin.flavors', function () { - it('should exist', function () { - expect(angular.module('horizon.dashboard.admin.flavors')).toBeDefined(); - }); - }); - -})(); diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.controller.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.controller.js deleted file mode 100644 index b5b7d3f4da..0000000000 --- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.controller.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -(function() { - 'use strict'; - - angular - .module('horizon.dashboard.admin.flavors') - .controller('FlavorsTableController', FlavorsTableController); - - FlavorsTableController.$inject = [ - 'horizon.app.core.openstack-service-api.nova' - ]; - - /** - * @ngdoc FlavorsTableController - * @ngController - * - * @description - * Controller for the flavors panel. - * Serves as the focal point for table actions. - */ - function FlavorsTableController( - nova - ) { - var ctrl = this; - - ctrl.flavors = []; - ctrl.iflavors = []; - - ctrl.searchFacets = getSearchFacets(); - - init(); - - //////////////////////////////// - - function init() { - nova.getFlavors(true, true).then(onGetFlavors); - } - - function onGetFlavors(response) { - ctrl.flavors = response.data.items; - } - - function getSearchFacets() { - return [ - { - label: gettext('Name'), - name: 'name', - singleton: true - }, - { - label: gettext('VCPUs'), - name: 'vcpus', - singleton: true - }, - { - label: gettext('RAM'), - name: 'ram', - singleton: true - }, - { - label: gettext('Public'), - name: 'os-flavor-access:is_public', - singleton: true, - options: [ - {label: gettext('Yes'), key: 'true'}, - {label: gettext('No'), key: 'false'} - ] - } - ]; - } - - } -})(); diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.controller.spec.js b/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.controller.spec.js deleted file mode 100644 index ab7ceabd60..0000000000 --- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.controller.spec.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -(function () { - 'use strict'; - - describe('horizon.dashboard.admin.flavors.controller.FlavorsTableController', function () { - - var flavors = [{id: '1'}, {id: '2'}]; - - var novaAPI = { - getFlavors: function() { - var deferred = $q.defer(); - deferred.resolve({data: {items: flavors}}); - return deferred.promise; - } - }; - - var controller, $q, $scope; - - beforeEach(module('horizon.framework')); - - beforeEach(module('horizon.app.core.openstack-service-api', function($provide) { - $provide.value('horizon.app.core.openstack-service-api.nova', novaAPI); - })); - - beforeEach(module('horizon.dashboard.admin', function($provide) { - $provide.constant('horizon.dashboard.admin.basePath', '/a/sample/path/'); - })); - - beforeEach(module('horizon.dashboard.admin.flavors')); - - beforeEach(inject(function ($injector, _$rootScope_) { - $scope = _$rootScope_.$new(); - $q = $injector.get('$q'); - controller = $injector.get('$controller'); - })); - - function createController() { - return controller('FlavorsTableController', {}); - } - - it('should set facets for search', function () { - var ctrl = createController(); - expect(ctrl.searchFacets).toBeDefined(); - expect(ctrl.searchFacets.length).toEqual(4); - expect(ctrl.searchFacets[0].name).toEqual('name'); - expect(ctrl.searchFacets[1].name).toEqual('vcpus'); - expect(ctrl.searchFacets[2].name).toEqual('ram'); - expect(ctrl.searchFacets[3].name).toEqual('os-flavor-access:is_public'); - }); - - it('should invoke nova apis', function() { - spyOn(novaAPI, 'getFlavors').and.callThrough(); - - var ctrl = createController(); - $scope.$apply(); - - expect(novaAPI.getFlavors).toHaveBeenCalled(); - expect(ctrl.flavors).toEqual(flavors); - expect(ctrl.iflavors).toBeDefined(); - }); - - }); - -})(); diff --git a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.html b/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.html deleted file mode 100644 index b6a578e7b5..0000000000 --- a/openstack_dashboard/dashboards/admin/static/dashboard/admin/flavors/table/flavors-table.html +++ /dev/null @@ -1,63 +0,0 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Flavor NameVCPUsRAMRoot DiskEphemeral DiskSwap DiskRX/TX factorIDPublicMetadata
- - {$ flavor.name $}{$ flavor.vcpus $}{$ flavor.ram | mb $}{$ flavor.disk | gb $}{$ flavor.ephemeral | gb $}{$ flavor.swap | mb $}{$ flavor.rxtx_factor $}{$ flavor.id $}{$ flavor.is_public | yesno $}{$ flavor.extras | hasExtras | yesno $} -
-
-
diff --git a/openstack_dashboard/enabled/_2000_admin.py b/openstack_dashboard/enabled/_2000_admin.py index 34363d770a..50972cd547 100644 --- a/openstack_dashboard/enabled/_2000_admin.py +++ b/openstack_dashboard/enabled/_2000_admin.py @@ -21,7 +21,6 @@ ADD_INSTALLED_APPS = [ ] ADD_ANGULAR_MODULES = [ - 'horizon.dashboard.admin', ] AUTO_DISCOVER_STATIC_FILES = True diff --git a/openstack_dashboard/enabled/_2080_admin_flavors_panel.py b/openstack_dashboard/enabled/_2080_admin_flavors_panel.py index ee4001895a..9e4109767f 100644 --- a/openstack_dashboard/enabled/_2080_admin_flavors_panel.py +++ b/openstack_dashboard/enabled/_2080_admin_flavors_panel.py @@ -1,3 +1,18 @@ +# (c) Copyright 2016 Hewlett Packard Enterprise Development LP +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # The slug of the panel to be added to HORIZON_CONFIG. Required. PANEL = 'flavors' # The slug of the dashboard the PANEL associated with. Required. diff --git a/openstack_dashboard/enabled/_2081_admin_flavors_panel.py b/openstack_dashboard/enabled/_2081_admin_flavors_panel.py deleted file mode 100644 index 7efcbd2066..0000000000 --- a/openstack_dashboard/enabled/_2081_admin_flavors_panel.py +++ /dev/null @@ -1,31 +0,0 @@ -# (c) Copyright 2015 Hewlett-Packard Development Company, L.P. -# (c) Copyright 2015 ThoughtWorks, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# The slug of the dashboard the PANEL associated with. Required. -PANEL_DASHBOARD = 'admin' - -# The slug of the panel group the PANEL is associated with. -# If you want the panel to show up without a panel group, -# use the panel group "default". -PANEL_GROUP = 'admin' - -# The slug of the panel to be added to HORIZON_CONFIG. Required. -PANEL = 'ngflavors' - -# If set to True, this settings file will not be added to the settings. -DISABLED = True - -# Python panel class of the PANEL to be added. -ADD_PANEL = 'openstack_dashboard.dashboards.admin.ngflavors.panel.NGFlavors' diff --git a/openstack_dashboard/local/local_settings.d/_2010_integration_tests_deprecated.py.example b/openstack_dashboard/local/local_settings.d/_2010_integration_tests_deprecated.py.example index 87c9e6718b..2028a2c7d9 100644 --- a/openstack_dashboard/local/local_settings.d/_2010_integration_tests_deprecated.py.example +++ b/openstack_dashboard/local/local_settings.d/_2010_integration_tests_deprecated.py.example @@ -2,4 +2,4 @@ # wanting to only test legacy panels. Since 'local' modules are evaluated # after settings.py, these configurations will override the default settings. -ANGULAR_FEATURES.update({"images_panel": False}) \ No newline at end of file +ANGULAR_FEATURES.update({"images_panel": False, "flavors_panel": False}) diff --git a/openstack_dashboard/settings.py b/openstack_dashboard/settings.py index 7a9c5a83b8..3ec6992f81 100644 --- a/openstack_dashboard/settings.py +++ b/openstack_dashboard/settings.py @@ -305,6 +305,7 @@ COMPRESS_OFFLINE_CONTEXT = 'horizon.themes.offline_context' # Dictionary of currently available angular features ANGULAR_FEATURES = { 'images_panel': True, + 'flavors_panel': False, } # Notice all customizable configurations should be above this line diff --git a/openstack_dashboard/static/app/core/core.module.js b/openstack_dashboard/static/app/core/core.module.js index 8ecfc58ff8..eebfb5c317 100644 --- a/openstack_dashboard/static/app/core/core.module.js +++ b/openstack_dashboard/static/app/core/core.module.js @@ -33,6 +33,7 @@ .module('horizon.app.core', [ 'horizon.app.core.conf', 'horizon.app.core.cloud-services', + 'horizon.app.core.flavors', 'horizon.app.core.images', 'horizon.app.core.metadata', 'horizon.app.core.openstack-service-api', diff --git a/openstack_dashboard/static/app/core/flavors/flavors.module.js b/openstack_dashboard/static/app/core/flavors/flavors.module.js new file mode 100644 index 0000000000..5f9b23daf7 --- /dev/null +++ b/openstack_dashboard/static/app/core/flavors/flavors.module.js @@ -0,0 +1,121 @@ +/** + * (c) Copyright 2015 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +(function() { + 'use strict'; + + /** + * @ngdoc overview + * @ngname horizon.app.core.flavors + * + * @description + * Provides all of the services and widgets required + * to support and display flavors related content. + */ + angular + .module('horizon.app.core.flavors', [ + 'ngRoute', + 'horizon.framework.conf', + 'horizon.app.core' + ]) + .constant('horizon.app.core.flavors.resourceType', 'OS::Nova::Flavor') + .run(run) + .config(config); + + run.$inject = [ + 'horizon.framework.conf.resource-type-registry.service', + 'horizon.app.core.flavors.basePath', + 'horizon.app.core.flavors.service', + 'horizon.app.core.flavors.resourceType' + ]; + + function run(registry, basePath, flavorsService, flavorResourceType) { + registry.getResourceType(flavorResourceType) + .setNames(gettext('Flavor'), gettext('Flavors')) + .setSummaryTemplateUrl(basePath + 'summary.html') + .setProperties(flavorProperties()) + .setListFunction(flavorsService.getFlavorsPromise) + .tableColumns + .append({ + id: 'name', + priority: 1 + }) + .append({ + id: 'vcpus', + priority: 2 + }) + .append({ + id: 'ram', + priority: 1, + sortDefault: true + }) + .append({ + id: 'disk', + priority: 2 + }) + .append({ + id: 'id', + priority: 1 + }) + .append({ + id: 'os-flavor-access:is_public', + priority: 2 + }); + + /** + * @name roleProperties + * @description resource properties for flavor module + */ + function flavorProperties() { + return { + name: gettext('Flavor Name'), + vcpus: gettext('VCPUs'), + ram: {label: gettext('RAM'), filters: ['mb']}, + disk: {label: gettext('Root Disk'), filters: ['gb']}, + 'OS-FLV-EXT-DATA:ephemeral': {label: gettext('Ephmeral Disk'), filters: ['gb']}, + swap: {label: gettext('Swap Disk'), filters: ['gb']}, + rxtx_factor: gettext('RX/TX Factor'), + id: gettext('ID'), + 'os-flavor-access:is_public': {label: gettext('Public'), filters: ['yesno']}, + metadata: gettext('Metadata') + }; + } + } + + config.$inject = [ + '$provide', + '$windowProvider', + '$routeProvider' + ]; + + /** + * @name config + * @param {Object} $provide + * @param {Object} $windowProvider + * @param {Object} $routeProvider + * @description Routes used by this module. + * @returns {undefined} Returns nothing + */ + function config($provide, $windowProvider, $routeProvider) { + var path = $windowProvider.$get().STATIC_URL + 'app/core/flavors/'; + $provide.constant('horizon.app.core.flavors.basePath', path); + + $routeProvider.when('/admin/flavors', { + templateUrl: path + 'panel.html' + }); + } + +})(); diff --git a/openstack_dashboard/static/app/core/flavors/flavors.service.js b/openstack_dashboard/static/app/core/flavors/flavors.service.js new file mode 100644 index 0000000000..fdb960ae4a --- /dev/null +++ b/openstack_dashboard/static/app/core/flavors/flavors.service.js @@ -0,0 +1,37 @@ +/* + * (c) Copyright 2016 Hewlett Packard Enterprise Development LP + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +(function() { + "use strict"; + + angular.module('horizon.app.core.flavors') + .factory('horizon.app.core.flavors.service', flavorsService); + + flavorsService.$inject = [ + 'horizon.app.core.openstack-service-api.nova' + ]; + + function flavorsService(nova) { + return { + getFlavorsPromise: getFlavorsPromise + }; + + function getFlavorsPromise(params) { + var fullParams = angular.extend({}, params, {get_extras: true}); + return nova.getFlavors(fullParams); + } + } + +})(); diff --git a/openstack_dashboard/static/app/core/flavors/flavors.service.spec.js b/openstack_dashboard/static/app/core/flavors/flavors.service.spec.js new file mode 100644 index 0000000000..76bb25aa2d --- /dev/null +++ b/openstack_dashboard/static/app/core/flavors/flavors.service.spec.js @@ -0,0 +1,41 @@ +/* + * (c) Copyright 2016 Hewlett Packard Enterprise Development LP + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +(function() { + "use strict"; + + describe('flavors service', function() { + var service; + beforeEach(module('horizon.framework.util')); + beforeEach(module('horizon.framework.conf')); + beforeEach(module('horizon.app.core.flavors')); + beforeEach(inject(function($injector) { + service = $injector.get('horizon.app.core.flavors.service'); + })); + + describe('getFlavorsPromise', function() { + it("provides a promise that gets translated", inject(function($q, $injector) { + var glance = $injector.get('horizon.app.core.openstack-service-api.nova'); + var deferred = $q.defer(); + spyOn(glance, 'getFlavors').and.returnValue(deferred.promise); + service.getFlavorsPromise({}); + deferred.resolve({data: {items: [{id: 1, updated_at: 'jul1'}]}}); + expect(glance.getFlavors).toHaveBeenCalled(); + })); + }); + + }); +})(); diff --git a/openstack_dashboard/static/app/core/flavors/panel.html b/openstack_dashboard/static/app/core/flavors/panel.html new file mode 100644 index 0000000000..4e30c10c38 --- /dev/null +++ b/openstack_dashboard/static/app/core/flavors/panel.html @@ -0,0 +1,3 @@ + + + diff --git a/openstack_dashboard/static/app/core/flavors/summary.html b/openstack_dashboard/static/app/core/flavors/summary.html new file mode 100644 index 0000000000..01b2a51968 --- /dev/null +++ b/openstack_dashboard/static/app/core/flavors/summary.html @@ -0,0 +1,19 @@ + + +
+
+
+
+
{$ key $}
+
{$ value $}
+
+
+
+
diff --git a/openstack_dashboard/static/app/core/openstack-service-api/nova.service.js b/openstack_dashboard/static/app/core/openstack-service-api/nova.service.js index 30a66e49f3..cd06208afa 100644 --- a/openstack_dashboard/static/app/core/openstack-service-api/nova.service.js +++ b/openstack_dashboard/static/app/core/openstack-service-api/nova.service.js @@ -468,14 +468,8 @@ * call per flavor). * @returns {Object} The result of the API call */ - function getFlavors(isPublic, getExtras) { - var config = {'params': {}}; - if (isPublic) { - config.params.is_public = 'true'; - } - if (getExtras) { - config.params.get_extras = 'true'; - } + function getFlavors(params) { + var config = params ? { 'params' : params} : { 'params' : {} }; return apiService.get('/api/nova/flavors/', config) .success(function (data) { // The colon character ':' in the flavor data causes problems when used diff --git a/openstack_dashboard/static/app/core/openstack-service-api/nova.service.spec.js b/openstack_dashboard/static/app/core/openstack-service-api/nova.service.spec.js index 967d2f7855..bd92338e5a 100644 --- a/openstack_dashboard/static/app/core/openstack-service-api/nova.service.spec.js +++ b/openstack_dashboard/static/app/core/openstack-service-api/nova.service.spec.js @@ -286,8 +286,6 @@ }, "error": "Unable to retrieve the flavors.", "testInput": [ - false, - false ] }, { @@ -301,8 +299,7 @@ }, "error": "Unable to retrieve the flavors.", "testInput": [ - true, - false + {is_public: "true"} ] }, { @@ -316,8 +313,7 @@ }, "error": "Unable to retrieve the flavors.", "testInput": [ - false, - true + {get_extras: "true"} ] }, { @@ -332,8 +328,7 @@ }, "error": "Unable to retrieve the flavors.", "testInput": [ - true, - true + {is_public: "true", get_extras: "true"} ] }, { diff --git a/openstack_dashboard/test/integration_tests/config.py b/openstack_dashboard/test/integration_tests/config.py index 2bcb6abb4d..668bc1d321 100644 --- a/openstack_dashboard/test/integration_tests/config.py +++ b/openstack_dashboard/test/integration_tests/config.py @@ -102,6 +102,12 @@ SeleniumGroup = [ help="Is the browser size maximized for each test?"), ] +FlavorsGroup = [ + cfg.StrOpt('panel_type', + default='legacy', + help='type/version of flavors panel'), +] + ScenarioGroup = [ cfg.StrOpt('ssh_user', default='cirros', @@ -163,6 +169,7 @@ def get_config(): cfg.CONF.register_opts(NetworkGroup, group="network") cfg.CONF.register_opts(AvailableServiceGroup, group="service_available") cfg.CONF.register_opts(SeleniumGroup, group="selenium") + cfg.CONF.register_opts(FlavorsGroup, group="flavors") cfg.CONF.register_opts(ImageGroup, group="image") cfg.CONF.register_opts(ScenarioGroup, group="scenario") cfg.CONF.register_opts(InstancesGroup, group="launch_instances") diff --git a/openstack_dashboard/test/integration_tests/horizon.conf b/openstack_dashboard/test/integration_tests/horizon.conf index a4eeba0080..a83249956a 100644 --- a/openstack_dashboard/test/integration_tests/horizon.conf +++ b/openstack_dashboard/test/integration_tests/horizon.conf @@ -33,6 +33,9 @@ explicit_wait=90 # (boolean) maximize_browser=yes +[flavors] +panel_type=legacy + [image] # http accessible image (string value) panel_type=angular diff --git a/openstack_dashboard/test/integration_tests/pages/admin/system/flavorspage.py b/openstack_dashboard/test/integration_tests/pages/admin/system/flavorspage.py index b28780e694..70da247248 100644 --- a/openstack_dashboard/test/integration_tests/pages/admin/system/flavorspage.py +++ b/openstack_dashboard/test/integration_tests/pages/admin/system/flavorspage.py @@ -15,6 +15,8 @@ from openstack_dashboard.test.integration_tests.regions import forms from openstack_dashboard.test.integration_tests.regions import menus from openstack_dashboard.test.integration_tests.regions import tables +from selenium.webdriver.common import by + class FlavorsTable(tables.TableRegion): name = "flavors" @@ -144,3 +146,12 @@ class FlavorsPage(basepage.BaseNavigationPage): def is_flavor_public(self, name): row = self._get_flavor_row(name) return row.cells[self.FLAVORS_TABLE_PUBLIC_COLUMN].text == "Yes" + + +class FlavorsPageNG(FlavorsPage): + _resource_page_header_locator = (by.By.CSS_SELECTOR, + 'hz-resource-panel hz-page-header h1') + + @property + def header(self): + return self._get_element(*self._resource_page_header_locator) diff --git a/openstack_dashboard/test/integration_tests/tests/test_flavors.py b/openstack_dashboard/test/integration_tests/tests/test_flavors.py index 5e0400b720..f427b0ccf8 100644 --- a/openstack_dashboard/test/integration_tests/tests/test_flavors.py +++ b/openstack_dashboard/test/integration_tests/tests/test_flavors.py @@ -12,10 +12,28 @@ import random +from openstack_dashboard.test.integration_tests import decorators from openstack_dashboard.test.integration_tests import helpers from openstack_dashboard.test.integration_tests.regions import messages +@decorators.config_option_required('flavors.panel_type', 'angular', + message="Legacy Panels not tested") +class TestFlavorAngular(helpers.AdminTestCase): + @property + def flavors_page(self): + from openstack_dashboard.test.integration_tests.pages.admin.\ + system.flavorspage import FlavorsPageNG + self.home_pg.go_to_system_flavorspage() + return FlavorsPageNG(self.driver, self.CONFIG) + + def test_basic_flavors_browse(self): + flavors_page = self.flavors_page + self.assertEqual(flavors_page.header.text, 'Flavors') + + +@decorators.config_option_required('flavors.panel_type', 'legacy', + message="Angular Panels not tested") class TestFlavors(helpers.AdminTestCase): FLAVOR_NAME = helpers.gen_random_resource_name("flavor") @@ -48,6 +66,18 @@ class TestFlavors(helpers.AdminTestCase): self.assertFalse( self.flavors_page.is_flavor_present(self.FLAVOR_NAME)) + def test_flavor_header(self): + header_text = self.driver.find_element_by_tag_name('h1').text + self.assertEqual(header_text, 'Flavors') + + def test_flavor_module_exists(self): + js_cmd = "$('html').append('
'"\ + " + angular.module('horizon.app.core.flavors').name"\ + " + '
');" + self.driver.execute_script(js_cmd) + value = self.driver.find_element_by_id('testonly').text + self.assertEqual(value, 'horizon.app.core.flavors') + def test_flavor_create(self): """tests the flavor creation and deletion functionalities: * creates a new flavor diff --git a/openstack_dashboard/test/settings.py b/openstack_dashboard/test/settings.py index 4aab9cf9f4..9b593061af 100644 --- a/openstack_dashboard/test/settings.py +++ b/openstack_dashboard/test/settings.py @@ -99,7 +99,8 @@ HORIZON_CONFIG = { } ANGULAR_FEATURES = { - 'images_panel': False # Use the legacy panel so unit tests are still run + 'images_panel': False, # Use the legacy panel so unit tests are still run + 'flavors_panel': False, } STATICFILES_DIRS = settings_utils.get_xstatic_dirs( diff --git a/releasenotes/notes/flavor-panel-switch-6b5cd5f0964f4ba3.yaml b/releasenotes/notes/flavor-panel-switch-6b5cd5f0964f4ba3.yaml new file mode 100644 index 0000000000..2c3812bc74 --- /dev/null +++ b/releasenotes/notes/flavor-panel-switch-6b5cd5f0964f4ba3.yaml @@ -0,0 +1,13 @@ +--- +prelude: > + The Flavor panel now may be configured to use + either the legacy or Angular code. +features: + - ANGULAR_FEATURES now allows for a key 'flavors_panel' to be + specified as True or False indicating whether the Angular + version of the panel is enabled. + - Integration tests for Flavor features may also be toggled + in openstack_dashboard/test/integration_tests/horizon.conf + using the 'panel_type' feature in the 'flavors' setting, + either set to 'legacy' or 'angular' to match the enabled + panel type.