horizon/openstack_dashboard/dashboards/project/instances/workflows/resize_instance.py
manchandavishal 6ac31e0ba8 Drop Django based implementation of launch instance
horizon already deprecated launch instance Django based implementation
in the wallaby cycle [1]. This patch remove code for launch instance
Django based implementation as angular based implementation is the
default one from long and all features gaps between angular and Django
implementation is closed.

It also moves SetAdvanced step code to ``resize_instance.py`` as
``workflows/create_instance.py`` file is deleted and remove server_group
option from Advanced Options of resizing instance action because
"server_group" is not required while resizing an instance as per
nova-api reference [2].

Closes-Bug: #1869222

[1] https://review.opendev.org/c/openstack/horizon/+/779125
[2] https://docs.openstack.org/api-ref/compute/?expanded=resize-server-resize-action-detail#resize-server-resize-action

Change-Id: I5e01cd81f309491f1a58ea93911030366a86e3c7
2022-01-24 16:21:18 +05:30

160 lines
6.2 KiB
Python

# Copyright 2013 CentRin Data, 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.
import json
from django.utils import encoding
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.debug import sensitive_variables
from horizon import exceptions
from horizon import forms
from horizon import workflows
from openstack_dashboard import api
from openstack_dashboard.dashboards.project.instances \
import utils as instance_utils
class SetAdvancedAction(workflows.Action):
disk_config = forms.ThemableChoiceField(
label=_("Disk Partition"), required=False,
help_text=_("Automatic: The entire disk is a single partition and "
"automatically resizes. Manual: Results in faster build "
"times but requires manual partitioning."))
config_drive = forms.BooleanField(
label=_("Configuration Drive"),
required=False, help_text=_("Configure OpenStack to write metadata to "
"a special configuration drive that "
"attaches to the instance when it boots."))
def __init__(self, request, context, *args, **kwargs):
super().__init__(request, context, *args, **kwargs)
try:
config_choices = [("AUTO", _("Automatic")),
("MANUAL", _("Manual"))]
self.fields['disk_config'].choices = config_choices
# Only show the Config Drive option for the Launch Instance
# is supported.
if context.get('workflow_slug') != 'launch_instance':
del self.fields['config_drive']
except Exception:
exceptions.handle(request, _('Unable to retrieve extensions '
'information.'))
class Meta(object):
name = _("Advanced Options")
help_text_template = ("project/instances/"
"_launch_advanced_help.html")
class SetAdvanced(workflows.Step):
action_class = SetAdvancedAction
contributes = ("disk_config", "config_drive",)
def prepare_action_context(self, request, context):
context = super().prepare_action_context(request, context)
# Add the workflow slug to the context so that we can tell which
# workflow is being used when creating the action. This step is
# used by both the Launch Instance and Resize Instance workflows.
context['workflow_slug'] = self.workflow.slug
return context
class SetFlavorChoiceAction(workflows.Action):
old_flavor_id = forms.CharField(required=False, widget=forms.HiddenInput())
old_flavor_name = forms.CharField(
label=_("Old Flavor"),
widget=forms.TextInput(attrs={'readonly': 'readonly'}),
required=False,
)
flavor = forms.ThemableChoiceField(
label=_("New Flavor"),
help_text=_("Choose the flavor to launch."))
class Meta(object):
name = _("Flavor Choice")
slug = 'flavor_choice'
help_text_template = ("project/instances/"
"_flavors_and_quotas.html")
def populate_flavor_choices(self, request, context):
old_flavor_id = context.get('old_flavor_id')
flavors = context.get('flavors').values()
# Remove current flavor from the list of flavor choices
flavors = [flavor for flavor in flavors if flavor.id != old_flavor_id]
if flavors:
if len(flavors) > 1:
flavors = instance_utils.sort_flavor_list(request, flavors)
else:
flavor = flavors[0]
flavors = [(flavor.id, flavor.name)]
flavors.insert(0, ("", _("Select a New Flavor")))
else:
flavors.insert(0, ("", _("No flavors available")))
return flavors
def get_help_text(self, extra_context=None):
extra = {} if extra_context is None else dict(extra_context)
try:
extra['usages'] = api.nova.tenant_absolute_limits(self.request,
reserved=True)
extra['usages_json'] = json.dumps(extra['usages'])
flavors = json.dumps([f._info for f in
instance_utils.flavor_list(self.request)])
extra['flavors'] = flavors
extra['resize_instance'] = True
except Exception:
exceptions.handle(self.request,
_("Unable to retrieve quota information."))
return super().get_help_text(extra)
class SetFlavorChoice(workflows.Step):
action_class = SetFlavorChoiceAction
depends_on = ("instance_id", "name")
contributes = ("old_flavor_id", "old_flavor_name", "flavors", "flavor")
class ResizeInstance(workflows.Workflow):
slug = "resize_instance"
name = _("Resize Instance")
finalize_button_name = _("Resize")
success_message = _('Request for resizing of instance "%s" '
'has been submitted.')
failure_message = _('Unable to resize instance "%s".')
success_url = "horizon:project:instances:index"
default_steps = (SetFlavorChoice, SetAdvanced,)
def format_status_message(self, message):
if "%s" in message:
return message % self.context.get('name', 'unknown instance')
return message
@sensitive_variables('context')
def handle(self, request, context):
instance_id = context.get('instance_id', None)
flavor = context.get('flavor', None)
disk_config = context.get('disk_config', None)
try:
api.nova.server_resize(request, instance_id, flavor, disk_config)
return True
except Exception as e:
self.failure_message = encoding.force_text(e)
return False