diff --git a/blazar_dashboard/api/client.py b/blazar_dashboard/api/client.py
index dad3ccf..e35a35a 100644
--- a/blazar_dashboard/api/client.py
+++ b/blazar_dashboard/api/client.py
@@ -124,6 +124,12 @@ def host_create(request, name, **kwargs):
return Host(host)
+def host_update(request, host_id, values):
+ """Update a host."""
+ host = blazarclient(request).host.update(host_id, values)
+ return Host(host)
+
+
def host_delete(request, host_id):
"""Delete a host."""
blazarclient(request).host.delete(host_id)
diff --git a/blazar_dashboard/content/hosts/forms.py b/blazar_dashboard/content/hosts/forms.py
new file mode 100644
index 0000000..956dbea
--- /dev/null
+++ b/blazar_dashboard/content/hosts/forms.py
@@ -0,0 +1,64 @@
+# 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 logging
+
+from django.utils.translation import ugettext_lazy as _
+from horizon import exceptions
+from horizon import forms
+from horizon import messages
+
+from blazar_dashboard import api
+
+LOG = logging.getLogger(__name__)
+
+
+class UpdateForm(forms.SelfHandlingForm):
+
+ class Meta(object):
+ name = _('Update Host Parameters')
+
+ host_id = forms.CharField(
+ label=_('Host ID'), widget=forms.widgets.HiddenInput, required=True)
+ values = forms.CharField(
+ label=_("Values to Update"),
+ required=True,
+ help_text=_('Enter values to update in JSON'),
+ widget=forms.Textarea(
+ attrs={'rows': 5}),
+ max_length=511)
+
+ def handle(self, request, data):
+ try:
+ api.client.host_update(self.request, host_id=data.get('host_id'),
+ values=data.get('values'))
+ messages.success(request, _("Host was successfully updated."))
+ return True
+ except Exception as e:
+ LOG.error('Error updating host: %s', e)
+ exceptions.handle(request,
+ message="An error occurred while updating this"
+ " host: %s. Please try again." % e)
+
+ def clean(self):
+ cleaned_data = super(UpdateForm, self).clean()
+
+ values = cleaned_data.get('values')
+ try:
+ values = eval(values)
+ cleaned_data['values'] = values
+ except (SyntaxError, NameError):
+ raise forms.ValidationError(
+ _('Values must written in JSON')
+ )
+
+ return cleaned_data
diff --git a/blazar_dashboard/content/hosts/tables.py b/blazar_dashboard/content/hosts/tables.py
index 0ee1be9..2760ec5 100644
--- a/blazar_dashboard/content/hosts/tables.py
+++ b/blazar_dashboard/content/hosts/tables.py
@@ -26,6 +26,13 @@ class CreateHosts(tables.LinkAction):
icon = "plus"
+class UpdateHost(tables.LinkAction):
+ name = "update"
+ verbose_name = _("Update Host")
+ url = "horizon:admin:hosts:update"
+ classes = ("btn-create", "ajax-modal")
+
+
class DeleteHost(tables.DeleteAction):
name = "delete"
data_type_singular = _("Host")
@@ -66,4 +73,4 @@ class HostsTable(tables.DataTable):
name = "hosts"
verbose_name = _("Hosts")
table_actions = (CreateHosts, DeleteHost,)
- row_actions = (DeleteHost,)
+ row_actions = (UpdateHost, DeleteHost,)
diff --git a/blazar_dashboard/content/hosts/templates/hosts/_update.html b/blazar_dashboard/content/hosts/templates/hosts/_update.html
new file mode 100644
index 0000000..7631bf5
--- /dev/null
+++ b/blazar_dashboard/content/hosts/templates/hosts/_update.html
@@ -0,0 +1,24 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}update_host{% endblock %}
+{% block form_action %}{% url 'horizon:admin:hosts:update' host.id %}{% endblock %}
+
+{% block modal_id %}update_host_modal{% endblock %}
+
+{% block modal-body %}
+
+
+
+
+
{% trans "Description" %}:
+
{% trans "Update extra capabilities of the host with the provided values." %}
+
+{% endblock %}
+
+{% block modal-footer %}
+
+ {% trans "Cancel" %}
+{% endblock %}
diff --git a/blazar_dashboard/content/hosts/templates/hosts/update.html b/blazar_dashboard/content/hosts/templates/hosts/update.html
new file mode 100644
index 0000000..2728be3
--- /dev/null
+++ b/blazar_dashboard/content/hosts/templates/hosts/update.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Update Host" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Update Host") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'admin/hosts/_update.html' %}
+{% endblock %}
diff --git a/blazar_dashboard/content/hosts/tests.py b/blazar_dashboard/content/hosts/tests.py
index c4c8894..46752c8 100644
--- a/blazar_dashboard/content/hosts/tests.py
+++ b/blazar_dashboard/content/hosts/tests.py
@@ -27,6 +27,8 @@ DETAIL_TEMPLATE = 'admin/hosts/detail.html'
DETAIL_URL_BASE = 'horizon:admin:hosts:detail'
CREATE_URL = reverse('horizon:admin:hosts:create')
CREATE_TEMPLATE = 'admin/hosts/create.html'
+UPDATE_URL_BASE = 'horizon:admin:hosts:update'
+UPDATE_TEMPLATE = 'admin/hosts/update.html'
class HostsTests(test.BaseAdminViewTests):
@@ -134,6 +136,53 @@ class HostsTests(test.BaseAdminViewTests):
self.assertMessageCount(success=(len(host_names) + 1))
self.assertRedirectsNoFollow(res, INDEX_URL)
+ @test.create_stubs({blazar_api.client: ('host_get', 'host_update')})
+ def test_update_host(self):
+ host = self.hosts.get(hypervisor_hostname='compute-1')
+ blazar_api.client.host_get(
+ IsA(http.HttpRequest),
+ host['id']
+ ).AndReturn(host)
+ blazar_api.client.host_update(
+ IsA(http.HttpRequest),
+ host_id=host['id'],
+ values={"key": "updated"}
+ )
+ form_data = {
+ 'host_id': host['id'],
+ 'values': '{"key": "updated"}'
+ }
+ self.mox.ReplayAll()
+
+ res = self.client.post(reverse(UPDATE_URL_BASE, args=[host['id']]),
+ form_data)
+ self.assertNoFormErrors(res)
+ self.assertMessageCount(success=1)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({blazar_api.client: ('host_get', 'host_update')})
+ def test_update_host_error(self):
+ host = self.hosts.get(hypervisor_hostname='compute-1')
+ blazar_api.client.host_get(
+ IsA(http.HttpRequest),
+ host['id']
+ ).AndReturn(host)
+ blazar_api.client.host_update(
+ IsA(http.HttpRequest),
+ host_id=host['id'],
+ values={"key": "updated"}
+ ).AndRaise(self.exceptions.blazar)
+ form_data = {
+ 'host_id': host['id'],
+ 'values': '{"key": "updated"}'
+ }
+ self.mox.ReplayAll()
+
+ res = self.client.post(reverse(UPDATE_URL_BASE, args=[host['id']]),
+ form_data)
+ self.assertNoFormErrors(res)
+ self.assertContains(res, 'An error occurred while updating')
+
@test.create_stubs({blazar_api.client: ('host_list', 'host_delete')})
def test_delete_host(self):
hosts = self.hosts.list()
diff --git a/blazar_dashboard/content/hosts/urls.py b/blazar_dashboard/content/hosts/urls.py
index 34d7a60..3d9588d 100644
--- a/blazar_dashboard/content/hosts/urls.py
+++ b/blazar_dashboard/content/hosts/urls.py
@@ -18,5 +18,7 @@ from blazar_dashboard.content.hosts import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^create/$', views.CreateView.as_view(), name='create'),
- url(r'^(?P[^/]+)/$', views.DetailView.as_view(), name='detail')
+ url(r'^(?P[^/]+)/$', views.DetailView.as_view(), name='detail'),
+ url(r'^(?P[^/]+)/update$', views.UpdateView.as_view(),
+ name='update'),
]
diff --git a/blazar_dashboard/content/hosts/views.py b/blazar_dashboard/content/hosts/views.py
index 0b1d46d..0ca9b79 100644
--- a/blazar_dashboard/content/hosts/views.py
+++ b/blazar_dashboard/content/hosts/views.py
@@ -10,13 +10,17 @@
# License for the specific language governing permissions and limitations
# under the License.
+from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
+from horizon import forms
from horizon import tables
from horizon import tabs
+from horizon.utils import memoized
from horizon import workflows
from blazar_dashboard import api
+from blazar_dashboard.content.hosts import forms as project_forms
from blazar_dashboard.content.hosts import tables as project_tables
from blazar_dashboard.content.hosts import tabs as project_tabs
from blazar_dashboard.content.hosts import workflows as project_workflows
@@ -45,3 +49,35 @@ class CreateView(workflows.WorkflowView):
workflow_class = project_workflows.CreateHostsWorkflow
template_name = 'admin/hosts/create.html'
page_title = _("Create Hosts")
+
+
+class UpdateView(forms.ModalFormView):
+ form_class = project_forms.UpdateForm
+ template_name = 'admin/hosts/update.html'
+ success_url = reverse_lazy('horizon:admin:hosts:index')
+
+ def get_initial(self):
+ initial = super(UpdateView, self).get_initial()
+
+ initial['host'] = self.get_object()
+ if initial['host']:
+ initial['host_id'] = initial['host'].id
+ initial['name'] = initial['host'].hypervisor_hostname
+
+ return initial
+
+ def get_context_data(self, **kwargs):
+ context = super(UpdateView, self).get_context_data(**kwargs)
+ context['host'] = self.get_object()
+ return context
+
+ @memoized.memoized_method
+ def get_object(self):
+ host_id = self.kwargs['host_id']
+ try:
+ host = api.client.host_get(self.request, host_id)
+ except Exception:
+ msg = _("Unable to retrieve host.")
+ redirect = reverse_lazy('horizon:admin:hosts:index')
+ exceptions.handle(self.request, msg, redirect=redirect)
+ return host