Merge "Support nova service-disable/enable for Hypervisor"
This commit is contained in:
commit
7896990631
@ -792,6 +792,18 @@ def service_list(request, binary=None):
|
||||
return novaclient(request).services.list(binary=binary)
|
||||
|
||||
|
||||
def service_enable(request, host, binary):
|
||||
return novaclient(request).services.enable(host, binary)
|
||||
|
||||
|
||||
def service_disable(request, host, binary, reason=None):
|
||||
if reason:
|
||||
return novaclient(request).services.disable_log_reason(host,
|
||||
binary, reason)
|
||||
else:
|
||||
return novaclient(request).services.disable(host, binary)
|
||||
|
||||
|
||||
def aggregate_details_list(request):
|
||||
result = []
|
||||
c = novaclient(request)
|
||||
|
@ -67,3 +67,28 @@ class EvacuateHostForm(forms.SelfHandlingForm):
|
||||
msg = _('Failed to evacuate host: %s.') % data['current_host']
|
||||
exceptions.handle(request, message=msg, redirect=redirect)
|
||||
return False
|
||||
|
||||
|
||||
class DisableServiceForm(forms.SelfHandlingForm):
|
||||
host = forms.CharField(label=_("Host"),
|
||||
widget=forms.TextInput(
|
||||
attrs={"readonly": "readonly"}))
|
||||
reason = forms.CharField(max_length=255,
|
||||
label=_("Reason"),
|
||||
required=False)
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
host = data["host"]
|
||||
reason = data["reason"]
|
||||
api.nova.service_disable(request, host, "nova-compute",
|
||||
reason=reason)
|
||||
msg = _("Disabled compute service for host: %s.") % host
|
||||
messages.success(request, msg)
|
||||
return True
|
||||
except Exception:
|
||||
redirect = reverse('horizon:admin:hypervisors:index')
|
||||
msg = _("Failed to disable compute service for host: %s.") % \
|
||||
data["host"]
|
||||
exceptions.handle(request, message=msg, redirect=redirect)
|
||||
return False
|
||||
|
@ -12,11 +12,13 @@
|
||||
|
||||
from django.template import defaultfilters as filters
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ungettext_lazy
|
||||
|
||||
from horizon import tables
|
||||
from horizon.utils import filters as utils_filters
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard import policy
|
||||
|
||||
|
||||
class EvacuateHost(tables.LinkAction):
|
||||
@ -37,6 +39,50 @@ class EvacuateHost(tables.LinkAction):
|
||||
return self.datum.state == "down"
|
||||
|
||||
|
||||
class DisableService(policy.PolicyTargetMixin, tables.LinkAction):
|
||||
name = "disable"
|
||||
verbose_name = _("Disable Service")
|
||||
url = "horizon:admin:hypervisors:compute:disable_service"
|
||||
classes = ("ajax-modal", "btn-confirm")
|
||||
policy_rules = (("compute", "compute_extension:services"),)
|
||||
|
||||
def allowed(self, request, service):
|
||||
if not api.nova.extension_supported('AdminActions', request):
|
||||
return False
|
||||
|
||||
return service.status == "enabled"
|
||||
|
||||
|
||||
class EnableService(policy.PolicyTargetMixin, tables.BatchAction):
|
||||
name = "enable"
|
||||
policy_rules = (("compute", "compute_extension:services"),)
|
||||
|
||||
@staticmethod
|
||||
def action_present(count):
|
||||
return ungettext_lazy(
|
||||
u"Enable Service",
|
||||
u"Enable Services",
|
||||
count
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def action_past(count):
|
||||
return ungettext_lazy(
|
||||
u"Enabled Service",
|
||||
u"Enabled Services",
|
||||
count
|
||||
)
|
||||
|
||||
def allowed(self, request, service):
|
||||
if not api.nova.extension_supported('AdminActions', request):
|
||||
return False
|
||||
|
||||
return service.status == "disabled"
|
||||
|
||||
def action(self, request, obj_id):
|
||||
api.nova.service_enable(request, obj_id, 'nova-compute')
|
||||
|
||||
|
||||
class ComputeHostFilterAction(tables.FilterAction):
|
||||
def filter(self, table, services, filter_string):
|
||||
q = filter_string.lower()
|
||||
@ -62,4 +108,4 @@ class ComputeHostTable(tables.DataTable):
|
||||
verbose_name = _("Compute Host")
|
||||
table_actions = (ComputeHostFilterAction,)
|
||||
multi_select = False
|
||||
row_actions = (EvacuateHost,)
|
||||
row_actions = (EvacuateHost, DisableService, EnableService)
|
||||
|
@ -94,4 +94,69 @@ class EvacuateHostViewTest(test.BaseAdminViewTests):
|
||||
res = self.client.post(url, form_data)
|
||||
dest_url = reverse('horizon:admin:hypervisors:index')
|
||||
self.assertMessageCount(error=1)
|
||||
self.assertRedirectsNoFollow(res, dest_url)
|
||||
self.assertRedirectsNoFollow(res, dest_url)
|
||||
|
||||
|
||||
class DisableServiceViewTest(test.BaseAdminViewTests):
|
||||
@test.create_stubs({api.nova: ('hypervisor_list',
|
||||
'hypervisor_stats')})
|
||||
def test_index(self):
|
||||
hypervisor = self.hypervisors.list().pop().hypervisor_hostname
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('horizon:admin:hypervisors:compute:disable_service',
|
||||
args=[hypervisor])
|
||||
res = self.client.get(url)
|
||||
template = 'admin/hypervisors/compute/disable_service.html'
|
||||
self.assertTemplateUsed(res, template)
|
||||
|
||||
@test.create_stubs({api.nova: ('hypervisor_list',
|
||||
'hypervisor_stats',
|
||||
'service_disable')})
|
||||
def test_successful_post(self):
|
||||
hypervisor = self.hypervisors.list().pop().hypervisor_hostname
|
||||
services = [service for service in self.services.list()
|
||||
if service.binary == 'nova-compute']
|
||||
|
||||
api.nova.service_disable(IsA(http.HttpRequest),
|
||||
services[0].host,
|
||||
'nova-compute',
|
||||
reason='test disable').AndReturn(True)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('horizon:admin:hypervisors:compute:disable_service',
|
||||
args=[hypervisor])
|
||||
|
||||
form_data = {'host': services[0].host,
|
||||
'reason': 'test disable'}
|
||||
|
||||
res = self.client.post(url, form_data)
|
||||
dest_url = reverse('horizon:admin:hypervisors:index')
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertMessageCount(success=1)
|
||||
self.assertRedirectsNoFollow(res, dest_url)
|
||||
|
||||
@test.create_stubs({api.nova: ('hypervisor_list',
|
||||
'hypervisor_stats',
|
||||
'service_disable')})
|
||||
def test_failing_nova_call_post(self):
|
||||
hypervisor = self.hypervisors.list().pop().hypervisor_hostname
|
||||
services = [service for service in self.services.list()
|
||||
if service.binary == 'nova-compute']
|
||||
|
||||
api.nova.service_disable(
|
||||
IsA(http.HttpRequest), services[0].host, 'nova-compute',
|
||||
reason='test disable').AndRaise(self.exceptions.nova)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('horizon:admin:hypervisors:compute:disable_service',
|
||||
args=[hypervisor])
|
||||
|
||||
form_data = {'host': services[0].host,
|
||||
'reason': 'test disable'}
|
||||
|
||||
res = self.client.post(url, form_data)
|
||||
dest_url = reverse('horizon:admin:hypervisors:index')
|
||||
self.assertMessageCount(error=1)
|
||||
self.assertRedirectsNoFollow(res, dest_url)
|
||||
|
@ -21,4 +21,7 @@ urlpatterns = patterns(
|
||||
url(r'^(?P<compute_host>[^/]+)/evacuate_host$',
|
||||
views.EvacuateHostView.as_view(),
|
||||
name='evacuate_host'),
|
||||
url(r'^(?P<compute_host>[^/]+)/disable_service$',
|
||||
views.DisableServiceView.as_view(),
|
||||
name='disable_service'),
|
||||
)
|
||||
|
@ -51,3 +51,20 @@ class EvacuateHostView(forms.ModalFormView):
|
||||
initial.update({'current_host': current_host,
|
||||
'hosts': hosts})
|
||||
return initial
|
||||
|
||||
|
||||
class DisableServiceView(forms.ModalFormView):
|
||||
form_class = project_forms.DisableServiceForm
|
||||
template_name = 'admin/hypervisors/compute/disable_service.html'
|
||||
context_object_name = 'compute_host'
|
||||
success_url = reverse_lazy("horizon:admin:hypervisors:index")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DisableServiceView, self).get_context_data(**kwargs)
|
||||
context["compute_host"] = self.kwargs['compute_host']
|
||||
return context
|
||||
|
||||
def get_initial(self):
|
||||
initial = super(DisableServiceView, self).get_initial()
|
||||
initial.update({'host': self.kwargs['compute_host']})
|
||||
return initial
|
||||
|
@ -0,0 +1,25 @@
|
||||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block form_id %}disable_service_form{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:admin:hypervisors:compute:disable_service' compute_host %}{% endblock %}
|
||||
|
||||
{% block modal-header %}{% trans "Disable Service" %}{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Disable the compute service." %}</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
<input class="btn btn-primary pull-right" type="submit" value="{% trans "Disable Service" %}" />
|
||||
<a href="{% url 'horizon:admin:hypervisors:index' %}" class="btn btn-default secondary cancel close">{% trans "Cancel" %}</a>
|
||||
{% endblock %}
|
@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Disable Service" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Disable Service") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'admin/hypervisors/compute/_disable_service.html' %}
|
||||
{% endblock %}
|
@ -50,9 +50,9 @@ class HypervisorViewTest(test.BaseAdminViewTests):
|
||||
if service.binary == 'nova-compute']
|
||||
self.assertItemsEqual(host_table.data, compute_services)
|
||||
actions_host_up = host_table.get_row_actions(host_table.data[0])
|
||||
self.assertEqual(0, len(actions_host_up))
|
||||
self.assertEqual(1, len(actions_host_up))
|
||||
actions_host_down = host_table.get_row_actions(host_table.data[1])
|
||||
self.assertEqual(1, len(actions_host_down))
|
||||
self.assertEqual(2, len(actions_host_down))
|
||||
self.assertEqual('evacuate', actions_host_down[0].name)
|
||||
|
||||
@test.create_stubs({api.nova: ('hypervisor_list',
|
||||
|
Loading…
x
Reference in New Issue
Block a user