Implement update host

Implemented update host functionality.
Also added test case for update host.

Partial-Implements: blueprint masakari-dashboard

Change-Id: I197440d069a1b5b49a234da8f05a01d45f222f2e
This commit is contained in:
nirajsingh 2018-01-30 18:41:40 +05:30
parent bef761d1d9
commit f463ab19f8
10 changed files with 208 additions and 13 deletions

View File

@ -153,6 +153,11 @@ def delete_host(request, host_id, segment_id):
host_id, segment_id, False) host_id, segment_id, False)
def get_host(request, segment_id, host_id): def update_host(request, host_uuid, failover_segment_id, fields_to_update):
"""return single host.""" return openstack_connection(request).update_host(
host_uuid, failover_segment_id, **fields_to_update)
def get_host(request, host_id, segment_id):
"""return single host """
return openstack_connection(request).get_host(host_id, segment_id) return openstack_connection(request).get_host(host_id, segment_id)

View File

@ -0,0 +1,71 @@
# Copyright (c) 2018 NTT DATA
#
# 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.
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon import messages
from masakaridashboard.api import api
class UpdateHostForm(forms.SelfHandlingForm):
uuid = forms.CharField(widget=forms.HiddenInput())
failover_segment_id = forms.CharField(widget=forms.HiddenInput())
name = forms.CharField(
label=_('Host Name'),
widget=forms.TextInput(attrs={'readonly': 'readonly'}))
reserved = forms.ChoiceField(
label=_('Reserved'),
choices=[('False', 'False'),
('True', 'True')],
widget=forms.Select(
attrs={'class': 'switchable',
'data-slug': 'available host'}),
required=False)
type = forms.CharField(
label=_('Type'),
widget=forms.TextInput(attrs={'maxlength': 255}))
control_attributes = forms.CharField(
label=_('Control Attribute'),
widget=forms.TextInput())
on_maintenance = forms.ChoiceField(
label=_('On Maintenance'),
choices=[('False', 'False'),
('True', 'True')],
widget=forms.Select(
attrs={'class': 'switchable',
'data-slug': 'available host'}),
required=False
)
def handle(self, request, data):
try:
attrs = {'name': data['name'],
'reserved': data['reserved'],
'type': data['type'],
'control_attributes': data['control_attributes'],
'on_maintenance': data['on_maintenance']}
api.update_host(request, data['uuid'],
data["failover_segment_id"], attrs)
msg = _('Successfully updated segment.')
messages.success(request, msg)
except Exception:
msg = _('Failed to update host.')
redirect = reverse('horizon:masakaridashboard:hosts:index')
exceptions.handle(request, msg, redirect=redirect)
return True

View File

@ -64,6 +64,18 @@ class DeleteHost(tables.DeleteAction):
exceptions.handle(self.request, msg, redirect=redirect) exceptions.handle(self.request, msg, redirect=redirect)
class UpdateHost(tables.LinkAction):
name = "update"
verbose_name = _("Update Host")
classes = ("ajax-modal",)
def get_link_url(self, datum):
host_id = datum.uuid+','+datum.failover_segment_id
url = "horizon:masakaridashboard:hosts:update"
return reverse(url, args=[host_id])
class HostTable(tables.DataTable): class HostTable(tables.DataTable):
name = tables.Column('name', verbose_name=_("Name"), name = tables.Column('name', verbose_name=_("Name"),
@ -71,8 +83,7 @@ class HostTable(tables.DataTable):
uuid = tables.Column('uuid', verbose_name=_("UUID")) uuid = tables.Column('uuid', verbose_name=_("UUID"))
reserved = tables.Column( reserved = tables.Column(
'reserved', verbose_name=_("Reserved")) 'reserved', verbose_name=_("Reserved"))
type = tables.Column( type = tables.WrappingColumn('type', verbose_name=_("Type"))
'type', verbose_name=_("Type"))
control_attributes = tables.Column( control_attributes = tables.Column(
'control_attributes', verbose_name=_( 'control_attributes', verbose_name=_(
"Control Attribute"), truncate=40) "Control Attribute"), truncate=40)
@ -89,3 +100,4 @@ class HostTable(tables.DataTable):
name = "host" name = "host"
verbose_name = _("Host") verbose_name = _("Host")
table_actions = (HostFilterAction, DeleteHost) table_actions = (HostFilterAction, DeleteHost)
row_actions = (UpdateHost,)

View File

@ -0,0 +1,6 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Modify reserved, type, on_maintenance and control_attributes of a host." %}</p>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Update Host" %}{% endblock %}
{% block main %}
{% include 'masakaridashboard/hosts/_update.html' %}
{% endblock %}

View File

@ -35,6 +35,7 @@ class HostTest(test.TestCase):
return_value=hosts): return_value=hosts):
res = self.client.get(INDEX_URL) res = self.client.get(INDEX_URL)
self.assertTemplateUsed(res, 'masakaridashboard/hosts/index.html') self.assertTemplateUsed(res, 'masakaridashboard/hosts/index.html')
self.assertEqual(res.status_code, 200)
def test_create_post(self): def test_create_post(self):
segment = self.masakari_segment.list() segment = self.masakari_segment.list()
@ -47,9 +48,9 @@ class HostTest(test.TestCase):
'segment_name': segment[0].name, 'segment_name': segment[0].name,
'name': host.name, 'name': host.name,
'type': host.type, 'type': host.type,
'reserved': '1', 'reserved': host.reserved,
'control_attributes': host.control_attributes, 'control_attributes': host.control_attributes,
'on_maintenance': '0' 'on_maintenance': host.on_maintenance
} }
with mock.patch('masakaridashboard.api.api.segment_list', with mock.patch('masakaridashboard.api.api.segment_list',
return_value=segment), mock.patch( return_value=segment), mock.patch(
@ -107,3 +108,45 @@ class HostTest(test.TestCase):
self.assertTemplateUsed(res, 'horizon/common/_detail.html') self.assertTemplateUsed(res, 'horizon/common/_detail.html')
self.assertTemplateUsed( self.assertTemplateUsed(
res, 'masakaridashboard/hosts/_detail_overview.html') res, 'masakaridashboard/hosts/_detail_overview.html')
def test_update(self):
host_to_update = self.masakari_host.list()[0]
id_to_update = (
host_to_update.uuid+','+host_to_update.failover_segment_id)
update_url = reverse('horizon:masakaridashboard:hosts:update',
args=[id_to_update])
host_to_update.control_attributes = 'fake'
form_data = {
'failover_segment_id': host_to_update.failover_segment_id,
'uuid': host_to_update.uuid,
'name': host_to_update.name,
'type': host_to_update.type,
'reserved': host_to_update.reserved,
'control_attributes': host_to_update.control_attributes,
'on_maintenance': host_to_update.on_maintenance
}
with mock.patch(
'masakaridashboard.api.api.get_host',
return_value=self.masakari_host.list()[0]), mock.patch(
'masakaridashboard.api.api.update_host',
return_value=host_to_update) as mocked_update:
res = self.client.post(update_url, form_data)
self.assertNoFormErrors(res)
self.assertEqual(res.status_code, 302)
self.assertRedirectsNoFollow(res, INDEX_URL)
fields_to_update = {
'name': host_to_update.name,
'type': host_to_update.type,
'reserved': host_to_update.reserved,
'control_attributes': host_to_update.control_attributes,
'on_maintenance': host_to_update.on_maintenance
}
mocked_update.assert_called_once_with(
mock.ANY,
host_to_update.uuid,
host_to_update.failover_segment_id,
fields_to_update
)

View File

@ -21,4 +21,5 @@ HOST = r'^(?P<host_id>[^/]+)/%s$'
urlpatterns = [ urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'), url(r'^$', views.IndexView.as_view(), name='index'),
url(HOST % 'detail', views.DetailView.as_view(), name='detail'), url(HOST % 'detail', views.DetailView.as_view(), name='detail'),
url(HOST % 'update', views.UpdateView.as_view(), name='update'),
] ]

View File

@ -14,14 +14,17 @@
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from horizon import exceptions from horizon import exceptions
from horizon import forms
from horizon import tables from horizon import tables
from horizon import tabs from horizon import tabs
from horizon.utils import memoized from horizon.utils import memoized
from masakaridashboard.api import api from masakaridashboard.api import api
from masakaridashboard.hosts import forms as host_forms
from masakaridashboard.hosts import tables as masakari_tab from masakaridashboard.hosts import tables as masakari_tab
from masakaridashboard.hosts import tabs as host_tab from masakaridashboard.hosts import tabs as host_tab
@ -74,7 +77,10 @@ class DetailView(tabs.TabbedTableView):
segment_id = row_data[1] segment_id = row_data[1]
host_id = row_data[0] host_id = row_data[0]
try: try:
host = api.get_host(self.request, segment_id, host_id) row_data = self.kwargs['host_id'].split(',')
segment_id = row_data[1]
host_id = row_data[0]
host = api.get_host(self.request, host_id, segment_id)
except Exception: except Exception:
msg = _('Unable to get host "%s".') % host_id msg = _('Unable to get host "%s".') % host_id
redirect = reverse('horizon:masakaridashboard:hosts:index') redirect = reverse('horizon:masakaridashboard:hosts:index')
@ -88,3 +94,47 @@ class DetailView(tabs.TabbedTableView):
def get_tabs(self, request, *args, **kwargs): def get_tabs(self, request, *args, **kwargs):
host = self.get_data() host = self.get_data()
return self.tab_group_class(request, host=host, **kwargs) return self.tab_group_class(request, host=host, **kwargs)
class UpdateView(forms.ModalFormView):
template_name = 'masakaridashboard/hosts/update.html'
modal_header = _("Update Host")
form_id = "update_host"
form_class = host_forms.UpdateHostForm
submit_label = _("Update")
submit_url = "horizon:masakaridashboard:hosts:update"
success_url = reverse_lazy("horizon:masakaridashboard:hosts:index")
page_title = _("Update Host")
@memoized.memoized_method
def get_object(self):
try:
row_data = self.kwargs['host_id'].split(',')
host_id = row_data[0]
segment_id = row_data[1]
host = api.get_host(self.request, host_id, segment_id)
return host
except Exception:
msg = _('Unable to retrieve host.')
redirect = reverse('horizon:masakaridashboard:hosts:index')
exceptions.handle(self.request, msg, redirect=redirect)
def get_context_data(self, **kwargs):
context = super(UpdateView, self).get_context_data(**kwargs)
context['submit_url'] = reverse(
self.submit_url,
args=[self.kwargs['host_id']]
)
return context
def get_initial(self, **kwargs):
host = self.get_object()
return {'name': host.name,
'reserved': host.reserved,
'type': host.type,
'control_attributes': host.control_attributes,
'on_maintenance': host.on_maintenance,
'uuid': host.uuid,
'failover_segment_id': host.failover_segment_id}

View File

@ -118,8 +118,8 @@ class AddHostForm(forms.SelfHandlingForm):
choices=[]) choices=[])
reserved = forms.ChoiceField( reserved = forms.ChoiceField(
label=_('Reserved'), label=_('Reserved'),
choices=[('0', 'False'), choices=[('False', 'False'),
('1', 'True')], ('True', 'True')],
widget=forms.Select( widget=forms.Select(
attrs={'class': 'switchable', attrs={'class': 'switchable',
'data-slug': 'available host'}), 'data-slug': 'available host'}),
@ -136,8 +136,8 @@ class AddHostForm(forms.SelfHandlingForm):
help_text=_("Attributes to control host.")) help_text=_("Attributes to control host."))
on_maintenance = forms.ChoiceField( on_maintenance = forms.ChoiceField(
label=_('On Maintenance'), label=_('On Maintenance'),
choices=[('0', 'False'), choices=[('False', 'False'),
('1', 'True')], ('True', 'True')],
widget=forms.Select( widget=forms.Select(
attrs={'class': 'switchable', attrs={'class': 'switchable',
'data-slug': 'available host'}), 'data-slug': 'available host'}),

View File

@ -44,10 +44,10 @@ def data(TEST):
TEST.masakari_host = test_data_utils.TestDataContainer() TEST.masakari_host = test_data_utils.TestDataContainer()
host1 = host.Host(uuid=uuidsentinel.host1, name="test", host1 = host.Host(uuid=uuidsentinel.host1, name="test",
reserved=True, type='service', reserved='True', type='service',
control_attributes='test', control_attributes='test',
failover_segment_id=uuidsentinel.segment1, failover_segment_id=uuidsentinel.segment1,
on_maintenance=False) on_maintenance='False')
TEST.masakari_host.add(host1) TEST.masakari_host.add(host1)