Restructure navigation and rename base directories
* overview is gone * deployment has been renamed overcloud * controller/compute/storage have been removed, as different tabs will be developed in a future patch * nodes now have tabbed navigation Change-Id: I7db58725dacb3d535be60be2cb31578a636d962d
This commit is contained in:
parent
ae4821b26b
commit
61f6b4e620
@ -17,33 +17,12 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
import horizon
|
import horizon
|
||||||
|
|
||||||
|
|
||||||
class InfrastructureOverview(horizon.PanelGroup):
|
class BasePanels(horizon.PanelGroup):
|
||||||
slug = "infrastructure_overview"
|
slug = "infrastructure"
|
||||||
name = _("Overview")
|
name = _("Infrastructure")
|
||||||
panels = (
|
panels = (
|
||||||
'overview',
|
'nodes',
|
||||||
)
|
'overcloud',
|
||||||
|
|
||||||
|
|
||||||
class Deployment(horizon.PanelGroup):
|
|
||||||
slug = "deployment"
|
|
||||||
name = _("Deployment")
|
|
||||||
panels = (
|
|
||||||
'deployment.overview',
|
|
||||||
'deployment.controller',
|
|
||||||
'deployment.compute',
|
|
||||||
'deployment.object_storage',
|
|
||||||
'deployment.block_storage',
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Nodes(horizon.PanelGroup):
|
|
||||||
slug = "nodes"
|
|
||||||
name = _("Nodes")
|
|
||||||
panels = (
|
|
||||||
'nodes.overview',
|
|
||||||
'nodes.resource',
|
|
||||||
'nodes.free',
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -51,11 +30,9 @@ class Infrastructure(horizon.Dashboard):
|
|||||||
name = _("Infrastructure")
|
name = _("Infrastructure")
|
||||||
slug = "infrastructure"
|
slug = "infrastructure"
|
||||||
panels = (
|
panels = (
|
||||||
InfrastructureOverview,
|
BasePanels,
|
||||||
Deployment,
|
|
||||||
Nodes,
|
|
||||||
)
|
)
|
||||||
default_panel = 'overview'
|
default_panel = 'overcloud'
|
||||||
permissions = ('openstack.roles.admin',)
|
permissions = ('openstack.roles.admin',)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
import horizon
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure import dashboard
|
|
||||||
|
|
||||||
|
|
||||||
class BlockStorage(horizon.Panel):
|
|
||||||
name = _("Block Storage")
|
|
||||||
slug = "deployment.block_storage"
|
|
||||||
|
|
||||||
|
|
||||||
dashboard.Infrastructure.register(BlockStorage)
|
|
@ -1,23 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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.conf.urls import defaults
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure.deployment.block_storage import views
|
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = defaults.patterns(
|
|
||||||
'',
|
|
||||||
defaults.url(r'^$', views.IndexView.as_view(), name='index'),
|
|
||||||
)
|
|
@ -1,18 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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.views import generic
|
|
||||||
|
|
||||||
|
|
||||||
class IndexView(generic.TemplateView):
|
|
||||||
template_name = 'infrastructure/base.html'
|
|
@ -1,27 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
import horizon
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure import dashboard
|
|
||||||
|
|
||||||
|
|
||||||
class Controller(horizon.Panel):
|
|
||||||
name = _("Controller")
|
|
||||||
slug = "deployment.controller"
|
|
||||||
|
|
||||||
|
|
||||||
dashboard.Infrastructure.register(Controller)
|
|
@ -1,23 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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.conf.urls import defaults
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure.deployment.controller import views
|
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = defaults.patterns(
|
|
||||||
'',
|
|
||||||
defaults.url(r'^$', views.IndexView.as_view(), name='index'),
|
|
||||||
)
|
|
@ -1,18 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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.views import generic
|
|
||||||
|
|
||||||
|
|
||||||
class IndexView(generic.TemplateView):
|
|
||||||
template_name = 'infrastructure/base.html'
|
|
@ -1,27 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
import horizon
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure import dashboard
|
|
||||||
|
|
||||||
|
|
||||||
class ObjectStorage(horizon.Panel):
|
|
||||||
name = _("Object Storage")
|
|
||||||
slug = "deployment.object_storage"
|
|
||||||
|
|
||||||
|
|
||||||
dashboard.Infrastructure.register(ObjectStorage)
|
|
@ -1,23 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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.conf.urls import defaults
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure.deployment.object_storage import views
|
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = defaults.patterns(
|
|
||||||
'',
|
|
||||||
defaults.url(r'^$', views.IndexView.as_view(), name='index'),
|
|
||||||
)
|
|
@ -1,18 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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.views import generic
|
|
||||||
|
|
||||||
|
|
||||||
class IndexView(generic.TemplateView):
|
|
||||||
template_name = 'infrastructure/base.html'
|
|
@ -1,27 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
#
|
|
||||||
# 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.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
import horizon
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure import dashboard
|
|
||||||
|
|
||||||
|
|
||||||
class DeploymentOverview(horizon.Panel):
|
|
||||||
name = _("Overview")
|
|
||||||
slug = "deployment.overview"
|
|
||||||
|
|
||||||
|
|
||||||
dashboard.Infrastructure.register(DeploymentOverview)
|
|
@ -1,23 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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.conf.urls import defaults
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure.deployment.overview import views
|
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = defaults.patterns(
|
|
||||||
'',
|
|
||||||
defaults.url(r'^$', views.IndexView.as_view(), name='index'),
|
|
||||||
)
|
|
@ -1,18 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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.views import generic
|
|
||||||
|
|
||||||
|
|
||||||
class IndexView(generic.TemplateView):
|
|
||||||
template_name = 'infrastructure/base.html'
|
|
@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure.nodes import tables
|
|
||||||
|
|
||||||
|
|
||||||
class FreeNodesTable(tables.NodesTable):
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
name = "free_nodes"
|
|
||||||
verbose_name = _("Free Nodes")
|
|
||||||
table_actions = ()
|
|
||||||
row_actions = ()
|
|
@ -1,12 +0,0 @@
|
|||||||
{% extends 'infrastructure/base_nodes_table.html' %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block title %}{% trans "Free Nodes" %}{% endblock %}
|
|
||||||
|
|
||||||
{% block page_header %}
|
|
||||||
{% include "horizon/common/_page_header.html" with title=_("Free Nodes") %}
|
|
||||||
{% endblock page_header %}
|
|
||||||
|
|
||||||
{% block name %}
|
|
||||||
{% trans "Free Nodes" %}
|
|
||||||
{% endblock %}
|
|
@ -1,58 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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 import urlresolvers
|
|
||||||
|
|
||||||
from mock import patch # noqa
|
|
||||||
|
|
||||||
from tuskar_ui import api
|
|
||||||
from tuskar_ui.test import helpers as test
|
|
||||||
|
|
||||||
|
|
||||||
INDEX_URL = urlresolvers.reverse('horizon:infrastructure:nodes.free'
|
|
||||||
':index')
|
|
||||||
NODES_OVERVIEW_URL = urlresolvers.reverse('horizon:infrastructure:'
|
|
||||||
'nodes.overview:index')
|
|
||||||
|
|
||||||
|
|
||||||
class FreeNodesTests(test.BaseAdminViewTests):
|
|
||||||
def setUp(self):
|
|
||||||
super(FreeNodesTests, self).setUp()
|
|
||||||
|
|
||||||
def test_index(self):
|
|
||||||
free_nodes = [api.Node(node)
|
|
||||||
for node in self.ironicclient_nodes.list()]
|
|
||||||
|
|
||||||
with patch('tuskar_ui.api.Node', **{
|
|
||||||
'spec_set': ['list'], # Only allow these attributes
|
|
||||||
'list.return_value': free_nodes,
|
|
||||||
}) as mock:
|
|
||||||
res = self.client.get(INDEX_URL)
|
|
||||||
self.assertEqual(mock.list.call_count, 1)
|
|
||||||
|
|
||||||
self.maxDiff = None
|
|
||||||
self.assertTemplateUsed(res,
|
|
||||||
'infrastructure/nodes.free/index.html')
|
|
||||||
self.assertItemsEqual(res.context['free_nodes_table'].data,
|
|
||||||
free_nodes)
|
|
||||||
|
|
||||||
def test_index_nodes_list_exception(self):
|
|
||||||
with patch('tuskar_ui.api.Node', **{
|
|
||||||
'spec_set': ['list'],
|
|
||||||
'list.side_effect': self.exceptions.tuskar,
|
|
||||||
}) as mock:
|
|
||||||
res = self.client.get(INDEX_URL)
|
|
||||||
self.assertEqual(mock.list.call_count, 1)
|
|
||||||
|
|
||||||
self.assertRedirectsNoFollow(res, NODES_OVERVIEW_URL)
|
|
@ -1,23 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
#
|
|
||||||
# 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.conf.urls import defaults
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure.nodes.free import views
|
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = defaults.patterns(
|
|
||||||
'',
|
|
||||||
defaults.url(r'^$', views.IndexView.as_view(), name='index'),
|
|
||||||
)
|
|
@ -1,39 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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 import urlresolvers
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
from horizon import exceptions
|
|
||||||
from horizon import tables as horizon_tables
|
|
||||||
|
|
||||||
from tuskar_ui import api as tuskar
|
|
||||||
from tuskar_ui.infrastructure.nodes.free import tables
|
|
||||||
|
|
||||||
|
|
||||||
class IndexView(horizon_tables.DataTableView):
|
|
||||||
table_class = tables.FreeNodesTable
|
|
||||||
template_name = 'infrastructure/nodes.free/index.html'
|
|
||||||
|
|
||||||
def get_data(self):
|
|
||||||
try:
|
|
||||||
free_nodes = tuskar.Node.list(self.request, associated=False)
|
|
||||||
except Exception:
|
|
||||||
free_nodes = []
|
|
||||||
redirect = urlresolvers.reverse(
|
|
||||||
'horizon:infrastructure:nodes.overview:index')
|
|
||||||
exceptions.handle(self.request,
|
|
||||||
_('Unable to retrieve free nodes.'),
|
|
||||||
redirect=redirect)
|
|
||||||
return free_nodes
|
|
@ -1,27 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
import horizon
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure import dashboard
|
|
||||||
|
|
||||||
|
|
||||||
class NodesOverview(horizon.Panel):
|
|
||||||
name = _("Overview")
|
|
||||||
slug = "nodes.overview"
|
|
||||||
|
|
||||||
|
|
||||||
dashboard.Infrastructure.register(NodesOverview)
|
|
@ -1,36 +0,0 @@
|
|||||||
{% extends 'infrastructure/base.html' %}
|
|
||||||
{% load i18n %}
|
|
||||||
{% load url from future %}
|
|
||||||
{% block title %}{% trans 'Nodes Overview' %}{% endblock %}
|
|
||||||
|
|
||||||
{% block page_header %}
|
|
||||||
{% include 'horizon/common/_domain_page_header.html' with title=_('Nodes Overview') %}
|
|
||||||
<div class="breadcrumbs">
|
|
||||||
<a href="{% url 'horizon:infrastructure:overview:index' %}"
|
|
||||||
>{% trans "Infrastructure" %}</a>
|
|
||||||
<span class="separator"></span>
|
|
||||||
</div>
|
|
||||||
{% endblock page_header %}
|
|
||||||
|
|
||||||
{% block main %}
|
|
||||||
<div class="row-fluid"><div class="span12">
|
|
||||||
<p>
|
|
||||||
<h4><span class="big-number">{{ nodes_total|default:0 }}</span> nodes in total</h4>
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
<p>
|
|
||||||
<a href="{% url 'horizon:infrastructure:nodes.resource:index' %}"
|
|
||||||
><span class="big-number">{{ nodes_allocated_resources|default:0 }}</span> Allocated — Resource Nodes</a>
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
<p>
|
|
||||||
<a href="{% url 'horizon:infrastructure:nodes.overview:register' %}"
|
|
||||||
class="btn ajax-modal pull-right">Register Nodes</a>
|
|
||||||
<a href="{% url 'horizon:infrastructure:nodes.free:index' %}"
|
|
||||||
><span class="big-number">{{ nodes_unallocated|default:0 }}</span> Unallocated Nodes</a>
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
<h4>Statistics</h4>
|
|
||||||
<p>No statistics available</p>
|
|
||||||
</div></div>
|
|
||||||
{% endblock %}
|
|
@ -1,63 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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_lazy
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
from django.views import generic
|
|
||||||
from horizon import exceptions
|
|
||||||
import horizon.forms
|
|
||||||
|
|
||||||
from tuskar_ui import api
|
|
||||||
from tuskar_ui.infrastructure.nodes import forms
|
|
||||||
|
|
||||||
|
|
||||||
class IndexView(generic.TemplateView):
|
|
||||||
template_name = 'infrastructure/nodes.overview/index.html'
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = super(IndexView, self).get_context_data(**kwargs)
|
|
||||||
try:
|
|
||||||
free_nodes = len(api.Node.list(self.request, associated=False))
|
|
||||||
except Exception:
|
|
||||||
free_nodes = 0
|
|
||||||
exceptions.handle(self.request,
|
|
||||||
_('Unable to retrieve free nodes.'))
|
|
||||||
try:
|
|
||||||
allocated_nodes = len(api.Node.list(self.request, associated=True))
|
|
||||||
except Exception:
|
|
||||||
allocated_nodes = 0
|
|
||||||
exceptions.handle(self.request,
|
|
||||||
_('Unable to retrieve allocated nodes.'))
|
|
||||||
context.update({
|
|
||||||
'nodes_total': free_nodes + allocated_nodes,
|
|
||||||
'nodes_allocated_resources': allocated_nodes,
|
|
||||||
'nodes_unallocated': free_nodes,
|
|
||||||
})
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
class RegisterView(horizon.forms.ModalFormView):
|
|
||||||
form_class = forms.NodeFormset
|
|
||||||
form_prefix = 'register_nodes'
|
|
||||||
template_name = 'infrastructure/nodes.overview/register.html'
|
|
||||||
success_url = reverse_lazy(
|
|
||||||
'horizon:infrastructure:nodes.overview:index')
|
|
||||||
|
|
||||||
def get_data(self):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def get_form(self, form_class):
|
|
||||||
return form_class(self.request.POST or None,
|
|
||||||
initial=self.get_data(),
|
|
||||||
prefix=self.form_prefix)
|
|
@ -19,9 +19,9 @@ import horizon
|
|||||||
from tuskar_ui.infrastructure import dashboard
|
from tuskar_ui.infrastructure import dashboard
|
||||||
|
|
||||||
|
|
||||||
class NodesFree(horizon.Panel):
|
class Nodes(horizon.Panel):
|
||||||
name = _("Free Nodes")
|
name = _("Nodes")
|
||||||
slug = "nodes.free"
|
slug = "nodes"
|
||||||
|
|
||||||
|
|
||||||
dashboard.Infrastructure.register(NodesFree)
|
dashboard.Infrastructure.register(Nodes)
|
@ -1,27 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
#
|
|
||||||
# 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.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
import horizon
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure import dashboard
|
|
||||||
|
|
||||||
|
|
||||||
class NodesResource(horizon.Panel):
|
|
||||||
name = _("Resource Nodes")
|
|
||||||
slug = "nodes.resource"
|
|
||||||
|
|
||||||
|
|
||||||
dashboard.Infrastructure.register(NodesResource)
|
|
@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure.nodes import tables
|
|
||||||
|
|
||||||
|
|
||||||
class ResourceNodesTable(tables.NodesTable):
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
name = "resource_nodes"
|
|
||||||
verbose_name = _("Resource Nodes")
|
|
||||||
table_actions = ()
|
|
||||||
row_actions = ()
|
|
@ -1,12 +0,0 @@
|
|||||||
{% extends 'infrastructure/base_nodes_table.html' %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block title %}{% trans "Resource Nodes" %}{% endblock %}
|
|
||||||
|
|
||||||
{% block page_header %}
|
|
||||||
{% include "horizon/common/_page_header.html" with title=_("Resource Nodes") %}
|
|
||||||
{% endblock page_header %}
|
|
||||||
|
|
||||||
{% block name %}
|
|
||||||
{% trans "Resource Nodes" %}
|
|
||||||
{% endblock %}
|
|
@ -1,59 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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 import urlresolvers
|
|
||||||
|
|
||||||
from mock import patch # noqa
|
|
||||||
|
|
||||||
from tuskar_ui import api
|
|
||||||
from tuskar_ui.test import helpers as test
|
|
||||||
|
|
||||||
|
|
||||||
INDEX_URL = urlresolvers.reverse('horizon:infrastructure:nodes.resource'
|
|
||||||
':index')
|
|
||||||
NODES_OVERVIEW_URL = urlresolvers.reverse('horizon:infrastructure:'
|
|
||||||
'nodes.overview:index')
|
|
||||||
|
|
||||||
|
|
||||||
class ResourceNodesTests(test.BaseAdminViewTests):
|
|
||||||
def setUp(self):
|
|
||||||
super(ResourceNodesTests, self).setUp()
|
|
||||||
|
|
||||||
def test_index(self):
|
|
||||||
resource_nodes = [api.Node(node)
|
|
||||||
for node in self.ironicclient_nodes.list()]
|
|
||||||
|
|
||||||
with patch('tuskar_ui.api.Node', **{
|
|
||||||
'spec_set': ['list'], # Only allow these attributes
|
|
||||||
'list.return_value': resource_nodes,
|
|
||||||
}) as mock:
|
|
||||||
res = self.client.get(INDEX_URL)
|
|
||||||
self.assertEqual(mock.list.call_count, 1)
|
|
||||||
|
|
||||||
self.maxDiff = None
|
|
||||||
self.assertTemplateUsed(
|
|
||||||
res, 'infrastructure/nodes.resource/index.html')
|
|
||||||
|
|
||||||
self.assertItemsEqual(res.context['resource_nodes_table'].data,
|
|
||||||
resource_nodes)
|
|
||||||
|
|
||||||
def test_index_nodes_list_exception(self):
|
|
||||||
with patch('tuskar_ui.api.Node', **{
|
|
||||||
'spec_set': ['list'],
|
|
||||||
'list.side_effect': self.exceptions.tuskar,
|
|
||||||
}) as mock:
|
|
||||||
res = self.client.get(INDEX_URL)
|
|
||||||
self.assertEqual(mock.list.call_count, 1)
|
|
||||||
|
|
||||||
self.assertRedirectsNoFollow(res, NODES_OVERVIEW_URL)
|
|
@ -1,23 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
#
|
|
||||||
# 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.conf.urls import defaults
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure.nodes.resource import views
|
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = defaults.patterns(
|
|
||||||
'',
|
|
||||||
defaults.url(r'^$', views.IndexView.as_view(), name='index'),
|
|
||||||
)
|
|
@ -1,39 +0,0 @@
|
|||||||
# -*- coding: utf8 -*-
|
|
||||||
#
|
|
||||||
# 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 import urlresolvers
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
from horizon import exceptions
|
|
||||||
from horizon import tables as horizon_tables
|
|
||||||
|
|
||||||
from tuskar_ui import api as tuskar
|
|
||||||
from tuskar_ui.infrastructure.nodes.resource import tables
|
|
||||||
|
|
||||||
|
|
||||||
class IndexView(horizon_tables.DataTableView):
|
|
||||||
table_class = tables.ResourceNodesTable
|
|
||||||
template_name = 'infrastructure/nodes.resource/index.html'
|
|
||||||
|
|
||||||
def get_data(self):
|
|
||||||
try:
|
|
||||||
resource_nodes = tuskar.Node.list(self.request, associated=True)
|
|
||||||
except Exception:
|
|
||||||
resource_nodes = []
|
|
||||||
redirect = urlresolvers.reverse(
|
|
||||||
'horizon:infrastructure:nodes.overview:index')
|
|
||||||
exceptions.handle(self.request,
|
|
||||||
_('Unable to retrieve resource nodes.'),
|
|
||||||
redirect=redirect)
|
|
||||||
return resource_nodes
|
|
@ -54,3 +54,21 @@ class NodesTable(tables.DataTable):
|
|||||||
|
|
||||||
def get_object_display(self, datum):
|
def get_object_display(self, datum):
|
||||||
return datum.uuid
|
return datum.uuid
|
||||||
|
|
||||||
|
|
||||||
|
class FreeNodesTable(NodesTable):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
name = "free_nodes"
|
||||||
|
verbose_name = _("Free Nodes")
|
||||||
|
table_actions = ()
|
||||||
|
row_actions = ()
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceNodesTable(NodesTable):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
name = "resource_nodes"
|
||||||
|
verbose_name = _("Resource Nodes")
|
||||||
|
table_actions = ()
|
||||||
|
row_actions = ()
|
||||||
|
93
tuskar_ui/infrastructure/nodes/tabs.py
Normal file
93
tuskar_ui/infrastructure/nodes/tabs.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2012 Nebula, Inc.
|
||||||
|
#
|
||||||
|
# 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 import urlresolvers
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from horizon import exceptions
|
||||||
|
from horizon import tabs
|
||||||
|
|
||||||
|
from tuskar_ui import api
|
||||||
|
from tuskar_ui.infrastructure.nodes import tables
|
||||||
|
|
||||||
|
|
||||||
|
class OverviewTab(tabs.Tab):
|
||||||
|
name = _("Overview")
|
||||||
|
slug = "overview"
|
||||||
|
template_name = ("infrastructure/nodes/_overview.html")
|
||||||
|
|
||||||
|
def get_context_data(self, request):
|
||||||
|
try:
|
||||||
|
free_nodes = len(api.Node.list(request, associated=False))
|
||||||
|
except Exception:
|
||||||
|
free_nodes = 0
|
||||||
|
exceptions.handle(request,
|
||||||
|
_('Unable to retrieve free nodes.'))
|
||||||
|
try:
|
||||||
|
resource_nodes = len(api.Node.list(request, associated=True))
|
||||||
|
except Exception:
|
||||||
|
resource_nodes = 0
|
||||||
|
exceptions.handle(request,
|
||||||
|
_('Unable to retrieve resource nodes.'))
|
||||||
|
return {
|
||||||
|
'nodes_total': free_nodes + resource_nodes,
|
||||||
|
'nodes_resources': resource_nodes,
|
||||||
|
'nodes_free': free_nodes,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceTab(tabs.TableTab):
|
||||||
|
table_classes = (tables.ResourceNodesTable,)
|
||||||
|
name = _("Resource")
|
||||||
|
slug = "resource"
|
||||||
|
template_name = ("horizon/common/_detail_table.html")
|
||||||
|
|
||||||
|
def get_resource_nodes_data(self):
|
||||||
|
try:
|
||||||
|
resource_nodes = api.Node.list(self.request, associated=True)
|
||||||
|
except Exception:
|
||||||
|
resource_nodes = []
|
||||||
|
redirect = urlresolvers.reverse(
|
||||||
|
'horizon:infrastructure:nodes:index')
|
||||||
|
exceptions.handle(self.request,
|
||||||
|
_('Unable to retrieve resource nodes.'),
|
||||||
|
redirect=redirect)
|
||||||
|
return resource_nodes
|
||||||
|
|
||||||
|
|
||||||
|
class FreeTab(tabs.TableTab):
|
||||||
|
table_classes = (tables.FreeNodesTable,)
|
||||||
|
name = _("Free")
|
||||||
|
slug = "free"
|
||||||
|
template_name = ("horizon/common/_detail_table.html")
|
||||||
|
|
||||||
|
def get_free_nodes_data(self):
|
||||||
|
try:
|
||||||
|
free_nodes = api.Node.list(self.request, associated=False)
|
||||||
|
except Exception:
|
||||||
|
free_nodes = []
|
||||||
|
redirect = urlresolvers.reverse(
|
||||||
|
'horizon:infrastructure:nodes:index')
|
||||||
|
exceptions.handle(self.request,
|
||||||
|
_('Unable to retrieve free nodes.'),
|
||||||
|
redirect=redirect)
|
||||||
|
return free_nodes
|
||||||
|
|
||||||
|
|
||||||
|
class NodeTabs(tabs.TabGroup):
|
||||||
|
slug = "nodes"
|
||||||
|
tabs = (OverviewTab, ResourceTab, FreeTab)
|
||||||
|
sticky = True
|
@ -3,17 +3,17 @@
|
|||||||
<div class="form form-inline">
|
<div class="form form-inline">
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
<h3 style="margin-bottom:16px">Node Detail</h3>
|
<h3 style="margin-bottom:16px">Node Detail</h3>
|
||||||
{% include 'infrastructure/nodes.overview/_nodes_formset_field.html' with field=form.node_tags %}
|
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.node_tags %}
|
||||||
</div>
|
</div>
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
<h4>Power Management</h4>
|
<h4>Power Management</h4>
|
||||||
{% include 'infrastructure/nodes.overview/_nodes_formset_field.html' with field=form.ip_address required=True %}
|
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.ip_address required=True %}
|
||||||
{% include 'infrastructure/nodes.overview/_nodes_formset_field.html' with field=form.ipmi_user %}
|
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.ipmi_user %}
|
||||||
{% include 'infrastructure/nodes.overview/_nodes_formset_field.html' with field=form.ipmi_password %}
|
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.ipmi_password %}
|
||||||
</div>
|
</div>
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
<h4>Networking</h4>
|
<h4>Networking</h4>
|
||||||
{% include 'infrastructure/nodes.overview/_nodes_formset_field.html' with field=form.mac_address required=True %}
|
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.mac_address required=True %}
|
||||||
</div>
|
</div>
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
<div class="span4">
|
<div class="span4">
|
||||||
@ -24,9 +24,9 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="row-fluid" id="register-hardware-fields">
|
<div class="row-fluid" id="register-hardware-fields">
|
||||||
{% include 'infrastructure/nodes.overview/_nodes_formset_field.html' with field=form.cpus extra_text=_('units') required=True %}
|
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.cpus extra_text=_('units') required=True %}
|
||||||
{% include 'infrastructure/nodes.overview/_nodes_formset_field.html' with field=form.memory extra_text=_('MB') required=True %}
|
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.memory extra_text=_('MB') required=True %}
|
||||||
{% include 'infrastructure/nodes.overview/_nodes_formset_field.html' with field=form.local_disk extra_text=_('GB') required=True %}
|
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.local_disk extra_text=_('GB') required=True %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -0,0 +1,24 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% load url from future%}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row-fluid"><div class="span12">
|
||||||
|
<p>
|
||||||
|
<h4><span class="big-number">{{ nodes_total|default:0 }}</span> {% trans 'nodes in total' %}</h4>
|
||||||
|
</p>
|
||||||
|
<hr>
|
||||||
|
<p>
|
||||||
|
<a href="{% url 'horizon:infrastructure:nodes:index' %}?tab=nodes__resource"
|
||||||
|
><span class="big-number">{{ nodes_resources|default:0 }}</span> {% trans 'Resource Nodes' %}</a>
|
||||||
|
</p>
|
||||||
|
<hr>
|
||||||
|
<p>
|
||||||
|
<a href="{% url 'horizon:infrastructure:nodes:register' %}"
|
||||||
|
class="btn ajax-modal pull-right">{% trans 'Register Nodes' %}</a>
|
||||||
|
<a href="{% url 'horizon:infrastructure:nodes:index' %}?tab=nodes__free"
|
||||||
|
><span class="big-number">{{ nodes_free|default:0 }}</span> {% trans 'Free Nodes' %}</a>
|
||||||
|
</p>
|
||||||
|
<hr>
|
||||||
|
<h4>{% trans 'Statistics' %}</h4>
|
||||||
|
<p>{% trans 'No statistics available' %}</p>
|
||||||
|
</div></div>
|
@ -3,18 +3,18 @@
|
|||||||
{% load url from future %}
|
{% load url from future %}
|
||||||
|
|
||||||
{% block form_id %}register_nodes_form{% endblock %}
|
{% block form_id %}register_nodes_form{% endblock %}
|
||||||
{% block form_action %}{% url 'horizon:infrastructure:nodes.overview:register' %}{% endblock %}
|
{% block form_action %}{% url 'horizon:infrastructure:nodes:register' %}{% endblock %}
|
||||||
{% block modal_id %}register_nodes_modal{% endblock %}
|
{% block modal_id %}register_nodes_modal{% endblock %}
|
||||||
{% block modal-header %}{% trans "Register Nodes" %}{% endblock %}
|
{% block modal-header %}{% trans "Register Nodes" %}{% endblock %}
|
||||||
|
|
||||||
{% block modal-body %}
|
{% block modal-body %}
|
||||||
{% include "formset_table/menu_formset.html" with formset=form form_template="infrastructure/nodes.overview/_nodes_formset_form.html" %}
|
{% include "formset_table/menu_formset.html" with formset=form form_template="infrastructure/nodes/_nodes_formset_form.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block modal-footer %}
|
{% block modal-footer %}
|
||||||
<input class="btn btn-primary pull-right" type="submit"
|
<input class="btn btn-primary pull-right" type="submit"
|
||||||
value="{% trans "Register Nodes" %}" />
|
value="{% trans "Register Nodes" %}" />
|
||||||
<a href="{% url 'horizon:infrastructure:nodes.overview:index' %}"
|
<a href="{% url 'horizon:infrastructure:nodes:index' %}"
|
||||||
class="btn secondary cancel close">{% trans "Cancel" %}</a>
|
class="btn secondary cancel close">{% trans "Cancel" %}</a>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
16
tuskar_ui/infrastructure/nodes/templates/nodes/index.html
Normal file
16
tuskar_ui/infrastructure/nodes/templates/nodes/index.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{% extends 'infrastructure/base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load url from future %}
|
||||||
|
{% block title %}{% trans 'Nodes' %}{% endblock %}
|
||||||
|
|
||||||
|
{% block page_header %}
|
||||||
|
{% include 'horizon/common/_domain_page_header.html' with title=_('Nodes') %}
|
||||||
|
{% endblock page_header %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span12">
|
||||||
|
{{ tab_group.render }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -7,5 +7,5 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
{% include "infrastructure/nodes.overview/_register.html" %}
|
{% include "infrastructure/nodes/_register.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -17,28 +17,86 @@ from django.core import urlresolvers
|
|||||||
from mock import patch, call # noqa
|
from mock import patch, call # noqa
|
||||||
|
|
||||||
from openstack_dashboard.test.test_data import utils
|
from openstack_dashboard.test.test_data import utils
|
||||||
|
from tuskar_ui import api as api
|
||||||
from tuskar_ui.test import helpers as test
|
from tuskar_ui.test import helpers as test
|
||||||
from tuskar_ui.test.test_data import tuskar_data
|
from tuskar_ui.test.test_data import tuskar_data
|
||||||
|
|
||||||
|
|
||||||
INDEX_URL = urlresolvers.reverse(
|
INDEX_URL = urlresolvers.reverse(
|
||||||
'horizon:infrastructure:nodes.overview:index')
|
'horizon:infrastructure:nodes:index')
|
||||||
REGISTER_URL = urlresolvers.reverse(
|
REGISTER_URL = urlresolvers.reverse(
|
||||||
'horizon:infrastructure:nodes.overview:register')
|
'horizon:infrastructure:nodes:register')
|
||||||
TEST_DATA = utils.TestDataContainer()
|
TEST_DATA = utils.TestDataContainer()
|
||||||
tuskar_data.data(TEST_DATA)
|
tuskar_data.data(TEST_DATA)
|
||||||
|
|
||||||
|
|
||||||
class RegisterNodesTests(test.BaseAdminViewTests):
|
class NodesTests(test.BaseAdminViewTests):
|
||||||
def test_index_get(self):
|
def test_index_get(self):
|
||||||
res = self.client.get(INDEX_URL)
|
res = self.client.get(INDEX_URL)
|
||||||
self.assertTemplateUsed(
|
self.assertTemplateUsed(
|
||||||
res, 'infrastructure/nodes.overview/index.html')
|
res, 'infrastructure/nodes/index.html')
|
||||||
|
self.assertTemplateUsed(res, 'infrastructure/nodes/_overview.html')
|
||||||
|
|
||||||
|
def test_free_nodes(self):
|
||||||
|
free_nodes = [api.Node(node)
|
||||||
|
for node in self.ironicclient_nodes.list()]
|
||||||
|
|
||||||
|
with patch('tuskar_ui.api.Node', **{
|
||||||
|
'spec_set': ['list'], # Only allow these attributes
|
||||||
|
'list.return_value': free_nodes,
|
||||||
|
}) as mock:
|
||||||
|
res = self.client.get(INDEX_URL + '?tab=nodes__free')
|
||||||
|
self.assertEqual(mock.list.call_count, 4)
|
||||||
|
|
||||||
|
self.maxDiff = None
|
||||||
|
self.assertTemplateUsed(res,
|
||||||
|
'infrastructure/nodes/index.html')
|
||||||
|
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
|
||||||
|
self.assertItemsEqual(res.context['free_nodes_table'].data,
|
||||||
|
free_nodes)
|
||||||
|
|
||||||
|
def test_free_nodes_list_exception(self):
|
||||||
|
with patch('tuskar_ui.api.Node', **{
|
||||||
|
'spec_set': ['list'],
|
||||||
|
'list.side_effect': self.exceptions.tuskar,
|
||||||
|
}) as mock:
|
||||||
|
res = self.client.get(INDEX_URL + '?tab=nodes__free')
|
||||||
|
self.assertEqual(mock.list.call_count, 3)
|
||||||
|
|
||||||
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||||
|
|
||||||
|
def test_resource_nodes(self):
|
||||||
|
resource_nodes = [api.Node(node)
|
||||||
|
for node in self.ironicclient_nodes.list()]
|
||||||
|
|
||||||
|
with patch('tuskar_ui.api.Node', **{
|
||||||
|
'spec_set': ['list'], # Only allow these attributes
|
||||||
|
'list.return_value': resource_nodes,
|
||||||
|
}) as mock:
|
||||||
|
res = self.client.get(INDEX_URL + '?tab=nodes__resource')
|
||||||
|
self.assertEqual(mock.list.call_count, 4)
|
||||||
|
|
||||||
|
self.maxDiff = None
|
||||||
|
self.assertTemplateUsed(
|
||||||
|
res, 'infrastructure/nodes/index.html')
|
||||||
|
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
|
||||||
|
self.assertItemsEqual(res.context['resource_nodes_table'].data,
|
||||||
|
resource_nodes)
|
||||||
|
|
||||||
|
def test_resource_nodes_list_exception(self):
|
||||||
|
with patch('tuskar_ui.api.Node', **{
|
||||||
|
'spec_set': ['list'],
|
||||||
|
'list.side_effect': self.exceptions.tuskar,
|
||||||
|
}) as mock:
|
||||||
|
res = self.client.get(INDEX_URL + '?tab=nodes__resource')
|
||||||
|
self.assertEqual(mock.list.call_count, 3)
|
||||||
|
|
||||||
|
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||||
|
|
||||||
def test_register_get(self):
|
def test_register_get(self):
|
||||||
res = self.client.get(REGISTER_URL)
|
res = self.client.get(REGISTER_URL)
|
||||||
self.assertTemplateUsed(
|
self.assertTemplateUsed(
|
||||||
res, 'infrastructure/nodes.overview/register.html')
|
res, 'infrastructure/nodes/register.html')
|
||||||
|
|
||||||
def test_register_post(self):
|
def test_register_post(self):
|
||||||
node = TEST_DATA.ironicclient_nodes.first
|
node = TEST_DATA.ironicclient_nodes.first
|
||||||
@ -104,4 +162,4 @@ class RegisterNodesTests(test.BaseAdminViewTests):
|
|||||||
['DE:AD:BE:EF:CA:FF'], None, u''),
|
['DE:AD:BE:EF:CA:FF'], None, u''),
|
||||||
])
|
])
|
||||||
self.assertTemplateUsed(
|
self.assertTemplateUsed(
|
||||||
res, 'infrastructure/nodes.overview/register.html')
|
res, 'infrastructure/nodes/register.html')
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
from django.conf import urls
|
from django.conf import urls
|
||||||
|
|
||||||
from tuskar_ui.infrastructure.nodes.overview import views
|
from tuskar_ui.infrastructure.nodes import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = urls.patterns(
|
urlpatterns = urls.patterns(
|
42
tuskar_ui/infrastructure/nodes/views.py
Normal file
42
tuskar_ui/infrastructure/nodes/views.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# -*- coding: utf8 -*-
|
||||||
|
#
|
||||||
|
# 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_lazy
|
||||||
|
|
||||||
|
import horizon.forms
|
||||||
|
from horizon import tabs as horizon_tabs
|
||||||
|
|
||||||
|
from tuskar_ui.infrastructure.nodes import forms
|
||||||
|
from tuskar_ui.infrastructure.nodes import tabs
|
||||||
|
|
||||||
|
|
||||||
|
class IndexView(horizon_tabs.TabbedTableView):
|
||||||
|
tab_group_class = tabs.NodeTabs
|
||||||
|
template_name = 'infrastructure/nodes/index.html'
|
||||||
|
|
||||||
|
|
||||||
|
class RegisterView(horizon.forms.ModalFormView):
|
||||||
|
form_class = forms.NodeFormset
|
||||||
|
form_prefix = 'register_nodes'
|
||||||
|
template_name = 'infrastructure/nodes/register.html'
|
||||||
|
success_url = reverse_lazy(
|
||||||
|
'horizon:infrastructure:nodes:index')
|
||||||
|
|
||||||
|
def get_data(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_form(self, form_class):
|
||||||
|
return form_class(self.request.POST or None,
|
||||||
|
initial=self.get_data(),
|
||||||
|
prefix=self.form_prefix)
|
@ -19,9 +19,9 @@ import horizon
|
|||||||
from tuskar_ui.infrastructure import dashboard
|
from tuskar_ui.infrastructure import dashboard
|
||||||
|
|
||||||
|
|
||||||
class Compute(horizon.Panel):
|
class Overcloud(horizon.Panel):
|
||||||
name = _("Compute")
|
name = _("Overcloud")
|
||||||
slug = "deployment.compute"
|
slug = "overcloud"
|
||||||
|
|
||||||
|
|
||||||
dashboard.Infrastructure.register(Compute)
|
dashboard.Infrastructure.register(Overcloud)
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
from django.conf.urls import defaults
|
from django.conf.urls import defaults
|
||||||
|
|
||||||
from tuskar_ui.infrastructure.deployment.compute import views
|
from tuskar_ui.infrastructure.overcloud import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = defaults.patterns(
|
urlpatterns = defaults.patterns(
|
@ -1,17 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
"""
|
|
||||||
Stub file to work around django bug: https://code.djangoproject.com/ticket/7198
|
|
||||||
"""
|
|
@ -1,27 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
#
|
|
||||||
# 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.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
import horizon
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure import dashboard
|
|
||||||
|
|
||||||
|
|
||||||
class Overview(horizon.Panel):
|
|
||||||
name = _("Overview")
|
|
||||||
slug = "overview"
|
|
||||||
|
|
||||||
|
|
||||||
dashboard.Infrastructure.register(Overview)
|
|
@ -1,12 +0,0 @@
|
|||||||
{% extends 'infrastructure/base.html' %}
|
|
||||||
{% load i18n %}
|
|
||||||
{% block title %}{% trans "Overview" %}{% endblock %}
|
|
||||||
|
|
||||||
{% block page_header %}
|
|
||||||
{% include "horizon/common/_page_header.html" with title=_("Overview") %}
|
|
||||||
{% endblock page_header %}
|
|
||||||
|
|
||||||
{% block infrastructure_main %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
#
|
|
||||||
# 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 openstack_dashboard.test import helpers as test
|
|
||||||
|
|
||||||
|
|
||||||
class OverviewTests(test.TestCase):
|
|
||||||
# Unit tests for overview.
|
|
||||||
def test_me(self):
|
|
||||||
self.assertTrue(1 + 1 == 2)
|
|
@ -1,23 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
#
|
|
||||||
# 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.conf.urls import defaults
|
|
||||||
|
|
||||||
from tuskar_ui.infrastructure.overview import views
|
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = defaults.patterns(
|
|
||||||
'',
|
|
||||||
defaults.url(r'^$', views.IndexView.as_view(), name='index'),
|
|
||||||
)
|
|
@ -1,24 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
#
|
|
||||||
# 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 horizon import views
|
|
||||||
|
|
||||||
|
|
||||||
class IndexView(views.APIView):
|
|
||||||
# A very simple class-based view...
|
|
||||||
template_name = 'infrastructure/overview/index.html'
|
|
||||||
|
|
||||||
def get_data(self, request, context, *args, **kwargs):
|
|
||||||
# Add data to the context here...
|
|
||||||
return context
|
|
@ -5,9 +5,7 @@
|
|||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
<div class="span12">
|
<div class="span12">
|
||||||
<div class="breadcrumbs">
|
<div class="breadcrumbs">
|
||||||
<a href="{% url 'horizon:infrastructure:overview:index' %}">{% trans "Infrastructure" %}</a>
|
<a href="{% url 'horizon:infrastructure:nodes:index' %}">{% trans "Nodes" %}</a>
|
||||||
<span class="separator"></span>
|
|
||||||
<a href="{% url 'horizon:infrastructure:nodes.overview:index' %}">{% trans "Nodes" %}</a>
|
|
||||||
<span class="separator"></span>
|
<span class="separator"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user