Merge "Undeploy in progress page"
This commit is contained in:
commit
36a0bc621b
@ -370,7 +370,7 @@ class Overcloud(base.APIResourceWrapper):
|
|||||||
|
|
||||||
the_overcloud = cls(object(), request=request)
|
the_overcloud = cls(object(), request=request)
|
||||||
# I need to mock attributes of overcloud that is being deleted.
|
# I need to mock attributes of overcloud that is being deleted.
|
||||||
the_overcloud.id = "deleting_in_progress"
|
the_overcloud.id = "overcloud"
|
||||||
|
|
||||||
if the_overcloud.stack and the_overcloud.is_deleting:
|
if the_overcloud.stack and the_overcloud.is_deleting:
|
||||||
return the_overcloud
|
return the_overcloud
|
||||||
@ -398,12 +398,6 @@ class Overcloud(base.APIResourceWrapper):
|
|||||||
found
|
found
|
||||||
:rtype: heatclient.v1.stacks.Stack or None
|
:rtype: heatclient.v1.stacks.Stack or None
|
||||||
"""
|
"""
|
||||||
# TODO(lsmola) load it properly, once the API has finished workflow
|
|
||||||
# and for example there can't be a situation when I delete Overcloud
|
|
||||||
# but Stack is still deleting. So the Overcloud will represent the
|
|
||||||
# state of all inner entities and operations correctly.
|
|
||||||
# Then also delete the try/except, it should not be caught on this
|
|
||||||
# level.
|
|
||||||
return heat.stack_get(self._request, 'overcloud')
|
return heat.stack_get(self._request, 'overcloud')
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
@ -449,7 +443,7 @@ class Overcloud(base.APIResourceWrapper):
|
|||||||
:rtype: bool
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
return self.stack.stack_status in ('CREATE_FAILED',
|
return self.stack.stack_status in ('CREATE_FAILED',
|
||||||
'UPDATE_FAILED')
|
'UPDATE_FAILED',)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def is_deleting(self):
|
def is_deleting(self):
|
||||||
@ -460,6 +454,15 @@ class Overcloud(base.APIResourceWrapper):
|
|||||||
"""
|
"""
|
||||||
return self.stack.stack_status in ('DELETE_IN_PROGRESS', )
|
return self.stack.stack_status in ('DELETE_IN_PROGRESS', )
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def is_delete_failed(self):
|
||||||
|
"""Check if this Overcloud deleting has failed.
|
||||||
|
|
||||||
|
:return: True if Overcloud deleting has failed, False otherwise.
|
||||||
|
:rtype: bool
|
||||||
|
"""
|
||||||
|
return self.stack.stack_status in ('DELETE_FAILED', )
|
||||||
|
|
||||||
@memoized.memoized
|
@memoized.memoized
|
||||||
def all_resources(self, with_joins=True):
|
def all_resources(self, with_joins=True):
|
||||||
"""Return a list of all Overcloud Resources
|
"""Return a list of all Overcloud Resources
|
||||||
@ -472,16 +475,9 @@ class Overcloud(base.APIResourceWrapper):
|
|||||||
are none
|
are none
|
||||||
:rtype: list of tuskar_ui.api.Resource
|
:rtype: list of tuskar_ui.api.Resource
|
||||||
"""
|
"""
|
||||||
# FIXME(lsmola) of this is a temporary hack. When I delete the stack
|
|
||||||
# there is a brief moment when list of resources throws an exception
|
|
||||||
# a second later, it does not. So the delete in progress page will
|
|
||||||
# need to be separated, because it is 'special'. Till then, this hack
|
|
||||||
# stays.
|
|
||||||
try:
|
try:
|
||||||
resources = [r for r in heat.resources_list(self._request,
|
resources = [r for r in heat.resources_list(self._request,
|
||||||
self.stack.stack_name)]
|
self.stack.stack_name)]
|
||||||
except heatclient.exc.HTTPNotFound:
|
|
||||||
resources = []
|
|
||||||
except heatclient.exc.HTTPInternalServerError:
|
except heatclient.exc.HTTPInternalServerError:
|
||||||
# TODO(lsmola) There is a weird bug in heat, that after
|
# TODO(lsmola) There is a weird bug in heat, that after
|
||||||
# stack-create it returns 500 for a little while. This can be
|
# stack-create it returns 500 for a little while. This can be
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
import heatclient
|
||||||
from horizon import tabs
|
from horizon import tabs
|
||||||
|
|
||||||
from tuskar_ui import api
|
from tuskar_ui import api
|
||||||
@ -100,6 +101,45 @@ class OverviewTab(tabs.Tab):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class UndeployInProgressTab(tabs.Tab):
|
||||||
|
name = _("Overview")
|
||||||
|
slug = "undeploy_in_progress_tab"
|
||||||
|
template_name = "infrastructure/overcloud/_undeploy_in_progress.html"
|
||||||
|
preload = False
|
||||||
|
|
||||||
|
def get_context_data(self, request, **kwargs):
|
||||||
|
overcloud = self.tab_group.kwargs['overcloud']
|
||||||
|
|
||||||
|
# TODO(lsmola) since at this point we don't have total number of nodes
|
||||||
|
# we will hack this around, till API can show this information. So it
|
||||||
|
# will actually show progress like the total number is 10, or it will
|
||||||
|
# show progress of 5%. Ugly, but workable.
|
||||||
|
total_num_nodes_count = 10
|
||||||
|
|
||||||
|
try:
|
||||||
|
all_resources_count = len(
|
||||||
|
overcloud.all_resources(with_joins=False))
|
||||||
|
except heatclient.exc.HTTPNotFound:
|
||||||
|
# Immediately after undeploying has started, heat returns this
|
||||||
|
# exception so we can take it as kind of init of undeploying.
|
||||||
|
all_resources_count = total_num_nodes_count
|
||||||
|
|
||||||
|
# TODO(lsmola) same as hack above
|
||||||
|
total_num_nodes_count = max(all_resources_count, total_num_nodes_count)
|
||||||
|
|
||||||
|
delete_progress = max(
|
||||||
|
5, 100 * (total_num_nodes_count - all_resources_count))
|
||||||
|
|
||||||
|
events = overcloud.stack_events
|
||||||
|
last_failed_events = [e for e in events
|
||||||
|
if e.resource_status == 'DELETE_FAILED'][-3:]
|
||||||
|
return {
|
||||||
|
'overcloud': overcloud,
|
||||||
|
'progress': delete_progress,
|
||||||
|
'last_failed_events': last_failed_events,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ConfigurationTab(tabs.TableTab):
|
class ConfigurationTab(tabs.TableTab):
|
||||||
table_classes = (tables.ConfigurationTable,)
|
table_classes = (tables.ConfigurationTable,)
|
||||||
name = _("Configuration")
|
name = _("Configuration")
|
||||||
@ -126,6 +166,12 @@ class LogTab(tabs.TableTab):
|
|||||||
return overcloud.stack_events
|
return overcloud.stack_events
|
||||||
|
|
||||||
|
|
||||||
|
class UndeployInProgressTabs(tabs.TabGroup):
|
||||||
|
slug = "undeploy_in_progress"
|
||||||
|
tabs = (UndeployInProgressTab, LogTab)
|
||||||
|
sticky = True
|
||||||
|
|
||||||
|
|
||||||
class DetailTabs(tabs.TabGroup):
|
class DetailTabs(tabs.TabGroup):
|
||||||
slug = "detail"
|
slug = "detail"
|
||||||
tabs = (OverviewTab, ConfigurationTab, LogTab)
|
tabs = (OverviewTab, ConfigurationTab, LogTab)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load url from future%}
|
{% load url from future%}
|
||||||
|
|
||||||
{% if overcloud.is_deploying or overcloud.is_failed or overcloud.is_deleting %}
|
{% if overcloud.is_deploying or overcloud.is_failed %}
|
||||||
{% if overcloud.is_deploying %}
|
{% if overcloud.is_deploying %}
|
||||||
<div class="alert alert-info">
|
<div class="alert alert-info">
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
@ -11,15 +11,6 @@
|
|||||||
<div class="bar bar-info" style="width:{{ progress }}%"></div>
|
<div class="bar bar-info" style="width:{{ progress }}%"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% elif overcloud.is_deleting %}
|
|
||||||
<div class="alert alert-error">
|
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="span2">
|
|
||||||
<strong>Undeploying...</strong>
|
|
||||||
<div class="progress progress-striped progress-danger">
|
|
||||||
<div class="bar bar-info" style="width:{{ progress }}%"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="alert alert-error">
|
<div class="alert alert-error">
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
@ -54,7 +45,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if not dashboard_urls and not overcloud.is_deploying and not overcloud.is_failed and not overcloud.is_deleting %}
|
{% if not dashboard_urls and not overcloud.is_deploying and not overcloud.is_failed %}
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
<div class="span8">
|
<div class="span8">
|
||||||
<p>Your OpenStack Deployment has been successfully deployed. It needs to be initialized before you will be able to use it.
|
<p>Your OpenStack Deployment has been successfully deployed. It needs to be initialized before you will be able to use it.
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span12">
|
||||||
|
<div class="actions pull-right">
|
||||||
|
</div>
|
||||||
|
{% if overcloud.is_deleting %}
|
||||||
|
<div class="alert alert-error">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span2">
|
||||||
|
<strong>Undeploying...</strong>
|
||||||
|
<div class="progress progress-striped progress-danger">
|
||||||
|
<div class="bar bar-info" style="width:{{ progress }}%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="alert alert-error">
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span2">
|
||||||
|
<strong>Undeploying failed</strong>
|
||||||
|
<div class="progress progress-striped progress-danger">
|
||||||
|
<div class="bar bar-info" style="width:{{ progress }}%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="span10">
|
||||||
|
{% if last_failed_events %}
|
||||||
|
<strong>{% trans "Last failed events:" %}</strong>
|
||||||
|
{% for event in last_failed_events %}
|
||||||
|
<div>
|
||||||
|
<dl>
|
||||||
|
<dt>{% trans "Timestamp" %}</dt>
|
||||||
|
<dd><time datetime="{{ event.event_time }}">{{ event.event_time }}</time></dd>
|
||||||
|
<dt>{% trans "Resource Name" %}</dt>
|
||||||
|
<dd>{{ event.resource_name }}</dd>
|
||||||
|
<dt>{% trans "Status" %}</dt>
|
||||||
|
<dd>{{ event.resource_status }}</dd>
|
||||||
|
<dt>{% trans "Reason" %}</dt>
|
||||||
|
<dd>{{ event.resource_status_reason }}</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
<a href="?tab=undeploy_in_progress__log" data-toggle="tab" data-target="#undeploy_in_progress__log" class="pull-right">See full log</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
(window.$ || window.addHorizonLoadEvent)(function () {
|
||||||
|
$('div > a[data-target="#undeploy_in_progress__log"]').click(function () {
|
||||||
|
$('li > a[data-target="#undeploy_in_progress__log"]').tab('show');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
@ -29,6 +29,11 @@ CREATE_URL = urlresolvers.reverse(
|
|||||||
'horizon:infrastructure:overcloud:create')
|
'horizon:infrastructure:overcloud:create')
|
||||||
DETAIL_URL = urlresolvers.reverse(
|
DETAIL_URL = urlresolvers.reverse(
|
||||||
'horizon:infrastructure:overcloud:detail', args=(1,))
|
'horizon:infrastructure:overcloud:detail', args=(1,))
|
||||||
|
UNDEPLOY_IN_PROGRESS_URL = urlresolvers.reverse(
|
||||||
|
'horizon:infrastructure:overcloud:undeploy_in_progress',
|
||||||
|
args=('overcloud',))
|
||||||
|
UNDEPLOY_IN_PROGRESS_URL_LOG_TAB = (
|
||||||
|
UNDEPLOY_IN_PROGRESS_URL + "?tab=undeploy_in_progress__log")
|
||||||
DETAIL_URL_CONFIGURATION_TAB = (DETAIL_URL +
|
DETAIL_URL_CONFIGURATION_TAB = (DETAIL_URL +
|
||||||
"?tab=detail__configuration")
|
"?tab=detail__configuration")
|
||||||
DETAIL_URL_LOG_TAB = (DETAIL_URL + "?tab=detail__log")
|
DETAIL_URL_LOG_TAB = (DETAIL_URL + "?tab=detail__log")
|
||||||
@ -70,7 +75,10 @@ def _mock_overcloud(**kwargs):
|
|||||||
'id',
|
'id',
|
||||||
'is_deployed',
|
'is_deployed',
|
||||||
'is_deploying',
|
'is_deploying',
|
||||||
|
'is_deleting',
|
||||||
|
'is_delete_failed',
|
||||||
'is_failed',
|
'is_failed',
|
||||||
|
'all_resources',
|
||||||
'resources',
|
'resources',
|
||||||
'stack',
|
'stack',
|
||||||
'stack_events',
|
'stack_events',
|
||||||
@ -86,7 +94,10 @@ def _mock_overcloud(**kwargs):
|
|||||||
'id': 1,
|
'id': 1,
|
||||||
'is_deployed': True,
|
'is_deployed': True,
|
||||||
'is_deploying': False,
|
'is_deploying': False,
|
||||||
|
'is_deleting': False,
|
||||||
|
'is_delete_failed': False,
|
||||||
'is_failed': False,
|
'is_failed': False,
|
||||||
|
'all_resources.return_value': [],
|
||||||
'resources.return_value': [],
|
'resources.return_value': [],
|
||||||
'stack_events': [],
|
'stack_events': [],
|
||||||
'stack': stack,
|
'stack': stack,
|
||||||
@ -102,7 +113,8 @@ def _mock_overcloud(**kwargs):
|
|||||||
class OvercloudTests(test.BaseAdminViewTests):
|
class OvercloudTests(test.BaseAdminViewTests):
|
||||||
|
|
||||||
def test_index_overcloud_undeployed_get(self):
|
def test_index_overcloud_undeployed_get(self):
|
||||||
with patch('tuskar_ui.api.Overcloud.list', return_value=[]):
|
with _mock_overcloud(**{'get_the_overcloud.side_effect': None,
|
||||||
|
'get_the_overcloud.return_value': None}):
|
||||||
res = self.client.get(INDEX_URL)
|
res = self.client.get(INDEX_URL)
|
||||||
|
|
||||||
self.assertRedirectsNoFollow(res, CREATE_URL)
|
self.assertRedirectsNoFollow(res, CREATE_URL)
|
||||||
@ -305,6 +317,41 @@ class OvercloudTests(test.BaseAdminViewTests):
|
|||||||
res = self.client.post(DELETE_URL)
|
res = self.client.post(DELETE_URL)
|
||||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||||
|
|
||||||
|
def test_undeploy_in_progress(self):
|
||||||
|
with _mock_overcloud(is_deleting=True, is_deployed=False):
|
||||||
|
res = self.client.get(UNDEPLOY_IN_PROGRESS_URL)
|
||||||
|
|
||||||
|
self.assertTemplateUsed(
|
||||||
|
res, 'infrastructure/overcloud/detail.html')
|
||||||
|
self.assertTemplateUsed(
|
||||||
|
res, 'infrastructure/overcloud/_undeploy_in_progress.html')
|
||||||
|
self.assertTemplateNotUsed(
|
||||||
|
res, 'horizon/common/_detail_table.html')
|
||||||
|
|
||||||
|
def test_undeploy_in_progress_finished(self):
|
||||||
|
with _mock_overcloud(**{'get_the_overcloud.side_effect': None,
|
||||||
|
'get_the_overcloud.return_value': None}):
|
||||||
|
res = self.client.get(UNDEPLOY_IN_PROGRESS_URL)
|
||||||
|
|
||||||
|
self.assertRedirectsNoFollow(res, CREATE_URL)
|
||||||
|
|
||||||
|
def test_undeploy_in_progress_invalid(self):
|
||||||
|
with _mock_overcloud():
|
||||||
|
res = self.client.get(UNDEPLOY_IN_PROGRESS_URL)
|
||||||
|
|
||||||
|
self.assertRedirectsNoFollow(res, DETAIL_URL)
|
||||||
|
|
||||||
|
def test_undeploy_in_progress_log_tab(self):
|
||||||
|
with _mock_overcloud(is_deleting=True, is_deployed=False):
|
||||||
|
res = self.client.get(UNDEPLOY_IN_PROGRESS_URL_LOG_TAB)
|
||||||
|
|
||||||
|
self.assertTemplateUsed(
|
||||||
|
res, 'infrastructure/overcloud/detail.html')
|
||||||
|
self.assertTemplateNotUsed(
|
||||||
|
res, 'infrastructure/overcloud/_undeploy_in_progress.html')
|
||||||
|
self.assertTemplateUsed(
|
||||||
|
res, 'horizon/common/_detail_table.html')
|
||||||
|
|
||||||
def test_scale_get(self):
|
def test_scale_get(self):
|
||||||
oc = None
|
oc = None
|
||||||
roles = TEST_DATA.tuskarclient_overcloud_roles.list()
|
roles = TEST_DATA.tuskarclient_overcloud_roles.list()
|
||||||
|
@ -21,6 +21,9 @@ urlpatterns = urls.patterns(
|
|||||||
'',
|
'',
|
||||||
urls.url(r'^$', views.IndexView.as_view(), name='index'),
|
urls.url(r'^$', views.IndexView.as_view(), name='index'),
|
||||||
urls.url(r'^create/$', views.CreateView.as_view(), name='create'),
|
urls.url(r'^create/$', views.CreateView.as_view(), name='create'),
|
||||||
|
urls.url(r'^(?P<overcloud_id>[^/]+)/undeploy-in-progress$',
|
||||||
|
views.UndeployInProgressView.as_view(),
|
||||||
|
name='undeploy_in_progress'),
|
||||||
urls.url(r'^create/role-edit/(?P<role_id>[^/]+)$',
|
urls.url(r'^create/role-edit/(?P<role_id>[^/]+)$',
|
||||||
views.OvercloudRoleEdit.as_view(), name='role_edit'),
|
views.OvercloudRoleEdit.as_view(), name='role_edit'),
|
||||||
urls.url(r'^(?P<overcloud_id>[^/]+)/$', views.DetailView.as_view(),
|
urls.url(r'^(?P<overcloud_id>[^/]+)/$', views.DetailView.as_view(),
|
||||||
|
@ -17,7 +17,10 @@ from django.core.urlresolvers import reverse
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.views.generic import base as base_views
|
from django.views.generic import base as base_views
|
||||||
|
|
||||||
|
import heatclient
|
||||||
|
from horizon import exceptions as horizon_exceptions
|
||||||
import horizon.forms
|
import horizon.forms
|
||||||
|
from horizon import messages
|
||||||
from horizon import tables as horizon_tables
|
from horizon import tables as horizon_tables
|
||||||
from horizon import tabs as horizon_tabs
|
from horizon import tabs as horizon_tabs
|
||||||
from horizon.utils import memoized
|
from horizon.utils import memoized
|
||||||
@ -33,6 +36,10 @@ from tuskar_ui.infrastructure.overcloud.workflows import undeployed
|
|||||||
|
|
||||||
|
|
||||||
INDEX_URL = 'horizon:infrastructure:overcloud:index'
|
INDEX_URL = 'horizon:infrastructure:overcloud:index'
|
||||||
|
DETAIL_URL = 'horizon:infrastructure:overcloud:detail'
|
||||||
|
CREATE_URL = 'horizon:infrastructure:overcloud:create'
|
||||||
|
UNDEPLOY_IN_PROGRESS_URL = (
|
||||||
|
'horizon:infrastructure:overcloud:undeploy_in_progress')
|
||||||
|
|
||||||
|
|
||||||
class OvercloudMixin(object):
|
class OvercloudMixin(object):
|
||||||
@ -60,22 +67,21 @@ class IndexView(base_views.RedirectView):
|
|||||||
|
|
||||||
def get_redirect_url(self):
|
def get_redirect_url(self):
|
||||||
try:
|
try:
|
||||||
# TODO(lsmola) implement this properly when supported by API
|
# TODO(lsmola) implement this properly when supported by API
|
||||||
overcloud = api.Overcloud.get_the_overcloud(self.request)
|
overcloud = api.Overcloud.get_the_overcloud(self.request)
|
||||||
except Exception:
|
except heatclient.exc.HTTPNotFound:
|
||||||
overcloud = None
|
overcloud = None
|
||||||
|
|
||||||
if overcloud is not None:
|
redirect = None
|
||||||
# TODO(lsmola) there can be a short period when overcloud
|
if overcloud is None:
|
||||||
# is created, but stack not. So we have to make sure we have
|
redirect = reverse(CREATE_URL)
|
||||||
# missing stack under control as a new STATE
|
elif overcloud.is_deleting or overcloud.is_delete_failed:
|
||||||
# Also when deleting now, it first deletes Overcloud then Stack
|
redirect = reverse(UNDEPLOY_IN_PROGRESS_URL,
|
||||||
# because stack takes much longer to delete. But we can probably
|
|
||||||
# ignore it for now and fix the worflow on API side.
|
|
||||||
redirect = reverse('horizon:infrastructure:overcloud:detail',
|
|
||||||
args=(overcloud.id,))
|
args=(overcloud.id,))
|
||||||
else:
|
else:
|
||||||
redirect = reverse('horizon:infrastructure:overcloud:create')
|
redirect = reverse(DETAIL_URL,
|
||||||
|
args=(overcloud.id,))
|
||||||
|
|
||||||
return redirect
|
return redirect
|
||||||
|
|
||||||
|
|
||||||
@ -103,7 +109,7 @@ class UndeployConfirmationView(horizon.forms.ModalFormView):
|
|||||||
template_name = 'infrastructure/overcloud/undeploy_confirmation.html'
|
template_name = 'infrastructure/overcloud/undeploy_confirmation.html'
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse('horizon:infrastructure:overcloud:index')
|
return reverse(INDEX_URL)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(UndeployConfirmationView,
|
context = super(UndeployConfirmationView,
|
||||||
@ -117,6 +123,42 @@ class UndeployConfirmationView(horizon.forms.ModalFormView):
|
|||||||
return initial
|
return initial
|
||||||
|
|
||||||
|
|
||||||
|
class UndeployInProgressView(horizon_tabs.TabView, OvercloudMixin, ):
|
||||||
|
tab_group_class = tabs.UndeployInProgressTabs
|
||||||
|
template_name = 'infrastructure/overcloud/detail.html'
|
||||||
|
|
||||||
|
def get_overcloud_or_redirect(self):
|
||||||
|
try:
|
||||||
|
# TODO(lsmola) implement this properly when supported by API
|
||||||
|
overcloud = api.Overcloud.get_the_overcloud(self.request)
|
||||||
|
except heatclient.exc.HTTPNotFound:
|
||||||
|
overcloud = None
|
||||||
|
|
||||||
|
if overcloud is None:
|
||||||
|
redirect = reverse(CREATE_URL)
|
||||||
|
messages.success(self.request,
|
||||||
|
_("Undeploying of the Overcloud has finished."))
|
||||||
|
raise horizon_exceptions.Http302(redirect)
|
||||||
|
elif overcloud.is_deleting or overcloud.is_delete_failed:
|
||||||
|
return overcloud
|
||||||
|
else:
|
||||||
|
messages.error(self.request,
|
||||||
|
_("Overcloud is not being undeployed."))
|
||||||
|
redirect = reverse(DETAIL_URL,
|
||||||
|
args=(overcloud.id,))
|
||||||
|
raise horizon_exceptions.Http302(redirect)
|
||||||
|
|
||||||
|
def get_tabs(self, request, **kwargs):
|
||||||
|
overcloud = self.get_overcloud_or_redirect()
|
||||||
|
return self.tab_group_class(request, overcloud=overcloud, **kwargs)
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(UndeployInProgressView,
|
||||||
|
self).get_context_data(**kwargs)
|
||||||
|
context['overcloud'] = self.get_overcloud_or_redirect()
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class Scale(horizon.workflows.WorkflowView, OvercloudMixin):
|
class Scale(horizon.workflows.WorkflowView, OvercloudMixin):
|
||||||
workflow_class = scale.Workflow
|
workflow_class = scale.Workflow
|
||||||
|
|
||||||
@ -154,7 +196,7 @@ class OvercloudRoleView(horizon_tables.DataTableView,
|
|||||||
|
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
overcloud = self.get_overcloud()
|
overcloud = self.get_overcloud()
|
||||||
redirect = reverse('horizon:infrastructure:overcloud:detail',
|
redirect = reverse(DETAIL_URL,
|
||||||
args=(overcloud.id,))
|
args=(overcloud.id,))
|
||||||
role = self.get_role(redirect)
|
role = self.get_role(redirect)
|
||||||
return self._get_nodes(overcloud, role)
|
return self._get_nodes(overcloud, role)
|
||||||
@ -163,7 +205,7 @@ class OvercloudRoleView(horizon_tables.DataTableView,
|
|||||||
context = super(OvercloudRoleView, self).get_context_data(**kwargs)
|
context = super(OvercloudRoleView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
overcloud = self.get_overcloud()
|
overcloud = self.get_overcloud()
|
||||||
redirect = reverse('horizon:infrastructure:overcloud:detail',
|
redirect = reverse(DETAIL_URL,
|
||||||
args=(overcloud.id,))
|
args=(overcloud.id,))
|
||||||
role = self.get_role(redirect)
|
role = self.get_role(redirect)
|
||||||
context['role'] = role
|
context['role'] = role
|
||||||
@ -185,7 +227,7 @@ class OvercloudRoleEdit(horizon.forms.ModalFormView, OvercloudRoleMixin):
|
|||||||
template_name = 'infrastructure/overcloud/role_edit.html'
|
template_name = 'infrastructure/overcloud/role_edit.html'
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse('horizon:infrastructure:overcloud:create')
|
return reverse(CREATE_URL)
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
role = self.get_role()
|
role = self.get_role()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user