Skip to content

Commit

Permalink
sort flavors on Resize Instance modal
Browse files Browse the repository at this point in the history
in the new flavor dropdown menu, it is sorted by id right now,
changed so that it matches that in create instance, sorted
 by ascending RAM usage

I refactored out the common flavor sorting code into instances/util.py
that is shared by create_instance and resize_instance

Change-Id: I40dedcf87dbcfb7128185445510d9ec96462abb2
Closes-Bug: #1279135
  • Loading branch information
clu-7 committed Feb 24, 2014
1 parent b771d46 commit 19eac27
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 49 deletions.
63 changes: 63 additions & 0 deletions openstack_dashboard/dashboards/project/instances/utils.py
@@ -0,0 +1,63 @@
# 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.

import logging

from django.conf import settings
from django.utils.translation import ugettext_lazy as _

from horizon import exceptions

from openstack_dashboard import api

LOG = logging.getLogger(__name__)


def flavor_list(request):
"""Utility method to retrieve a list of flavors."""
try:
return api.nova.flavor_list(request)
except Exception:
exceptions.handle(request,
_('Unable to retrieve instance flavors.'))
return []


def sort_flavor_list(request, flavors):
"""Utility method to sort a list of flavors.
By default, returns the available flavors, sorted by RAM
usage (ascending). Override these behaviours with a
CREATE_INSTANCE_FLAVOR_SORT dict
in local_settings.py.
"""
def get_key(flavor, sort_key):
try:
return getattr(flavor, sort_key)
except AttributeError:
LOG.warning('Could not find sort key "%s". Using the default '
'"ram" instead.', sort_key)
return getattr(flavor, 'ram')
try:
flavor_sort = getattr(settings, 'CREATE_INSTANCE_FLAVOR_SORT', {})
sort_key = flavor_sort.get('key', 'ram')
rev = flavor_sort.get('reverse', False)
if not callable(sort_key):
key = lambda flavor: get_key(flavor, sort_key)
else:
key = sort_key
flavor_list = [(flavor.id, '%s' % flavor.name)
for flavor in sorted(flavors, key=key, reverse=rev)]
return flavor_list
except Exception:
exceptions.handle(request,
_('Unable to sort instance flavors.'))
return []
Expand Up @@ -21,7 +21,6 @@
import json
import logging

from django.conf import settings
from django.template.defaultfilters import filesizeformat # noqa
from django.utils.text import normalize_newlines # noqa
from django.utils.translation import ugettext_lazy as _
Expand All @@ -40,22 +39,15 @@
from openstack_dashboard.api import cinder
from openstack_dashboard.usage import quotas

from openstack_dashboard.dashboards.project.images import utils
from openstack_dashboard.dashboards.project.images \
import utils as image_utils
from openstack_dashboard.dashboards.project.instances \
import utils as instance_utils


LOG = logging.getLogger(__name__)


def _flavor_list(request):
"""Utility method to retrieve a list of flavor."""
try:
return api.nova.flavor_list(request)
except Exception:
exceptions.handle(request,
_('Unable to retrieve instance flavors.'))
return []


class SelectProjectUserAction(workflows.Action):
project_id = forms.ChoiceField(label=_("Project"))
user_id = forms.ChoiceField(label=_("User"))
Expand Down Expand Up @@ -203,7 +195,7 @@ def clean(self):
# however get_available_images uses a cache of image list,
# so it is used instead of image_get to reduce the number
# of API calls.
images = utils.get_available_images(
images = image_utils.get_available_images(
self.request,
self.context.get('project_id'),
self._images_cache)
Expand All @@ -217,7 +209,7 @@ def clean(self):
# however flavor_list uses a memoized decorator
# so it is used instead of flavor_get to reduce the number
# of API calls.
flavors = _flavor_list(self.request)
flavors = instance_utils.flavor_list(self.request)
flavor = [x for x in flavors if x.id == flavor_id][0]
except IndexError:
flavor = None
Expand Down Expand Up @@ -277,30 +269,9 @@ def clean(self):
return cleaned_data

def populate_flavor_choices(self, request, context):
"""By default, returns the available flavors, sorted by RAM
usage (ascending).
Override these behaviours with a CREATE_INSTANCE_FLAVOR_SORT dict
in local_settings.py.
"""
def get_key(flavor, sort_key):
try:
return getattr(flavor, sort_key)
except AttributeError:
LOG.warning('Could not find sort key "%s". Using the default '
'"ram" instead.', sort_key)
return getattr(flavor, 'ram')

flavors = _flavor_list(request)
flavors = instance_utils.flavor_list(request)
if flavors:
flavor_sort = getattr(settings, 'CREATE_INSTANCE_FLAVOR_SORT', {})
rev = flavor_sort.get('reverse', False)
sort_key = flavor_sort.get('key', 'ram')
if not callable(sort_key):
key = lambda flavor: get_key(flavor, sort_key)
else:
key = sort_key
return [(flavor.id, "%s" % flavor.name)
for flavor in sorted(flavors, key=key, reverse=rev)]
return instance_utils.sort_flavor_list(request, flavors)
return []

def populate_availability_zone_choices(self, request, context):
Expand All @@ -325,9 +296,10 @@ def get_help_text(self):
try:
extra['usages'] = api.nova.tenant_absolute_limits(self.request)
extra['usages_json'] = json.dumps(extra['usages'])
flavors = json.dumps([f._info for f in _flavor_list(self.request)])
flavors = json.dumps([f._info for f in
instance_utils.flavor_list(self.request)])
extra['flavors'] = flavors
images = utils.get_available_images(self.request,
images = image_utils.get_available_images(self.request,
self.initial['project_id'],
self._images_cache)
if images is not None:
Expand Down Expand Up @@ -361,7 +333,7 @@ def _get_volume_display_name(self, volume):

def populate_image_id_choices(self, request, context):
choices = []
images = utils.get_available_images(request,
images = image_utils.get_available_images(request,
context.get('project_id'),
self._images_cache)
for image in images:
Expand All @@ -376,7 +348,7 @@ def populate_image_id_choices(self, request, context):
return choices

def populate_instance_snapshot_id_choices(self, request, context):
images = utils.get_available_images(request,
images = image_utils.get_available_images(request,
context.get('project_id'),
self._images_cache)
choices = [(image.id, image.name)
Expand Down
Expand Up @@ -26,6 +26,9 @@

from openstack_dashboard import api

from openstack_dashboard.dashboards.project.instances \
import utils as instance_utils


class SetFlavorChoiceAction(workflows.Action):
old_flavor_id = forms.CharField(required=False, widget=forms.HiddenInput())
Expand Down Expand Up @@ -54,22 +57,22 @@ def clean(self):
return cleaned_data

def populate_flavor_choices(self, request, context):
flavors = context.get('flavors')
flavor_list = [(flavor.id, '%s' % flavor.name)
for flavor in flavors.values()]
if flavor_list:
flavor_list.insert(0, ("", _("Select an New Flavor")))
flavors = context.get('flavors').values()
if len(flavors) > 1:
flavors = instance_utils.sort_flavor_list(request, flavors)
if flavors:
flavors.insert(0, ("", _("Select a New Flavor")))
else:
flavor_list.insert(0, ("", _("No flavors available")))
return sorted(flavor_list)
flavors.insert(0, ("", _("No flavors available")))
return flavors

def get_help_text(self):
extra = {}
try:
extra['usages'] = api.nova.tenant_absolute_limits(self.request)
extra['usages_json'] = json.dumps(extra['usages'])
flavors = json.dumps([f._info for f in
api.nova.flavor_list(self.request)])
instance_utils.flavor_list(self.request)])
extra['flavors'] = flavors
except Exception:
exceptions.handle(self.request,
Expand Down

0 comments on commit 19eac27

Please sign in to comment.