Merge "Support nova service-disable/enable for Hypervisor"

This commit is contained in:
Jenkins 2014-11-26 09:04:19 +00:00 committed by Gerrit Code Review
commit 7896990631
9 changed files with 208 additions and 4 deletions

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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'),
)

View File

@ -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

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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',