diff options
author | Jenkins <jenkins@review.openstack.org> | 2013-12-05 17:09:26 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2013-12-05 17:09:26 +0000 |
commit | 127e0195ad8b870a97ceaa6344c40e720d9db4b6 (patch) | |
tree | 2a82adb1cecb02914168dcbab652e057d9a28daa | |
parent | c3096ea60897155f62d31403103aae384f39b4b8 (diff) | |
parent | 25a466fe0795a7ad46fe11e82c0b3caca91678f6 (diff) | |
download | tuskar-ui-127e0195ad8b870a97ceaa6344c40e720d9db4b6.tar.gz |
Merge "New structure of panels"
115 files changed, 833 insertions, 5470 deletions
diff --git a/tuskar_ui/infrastructure/dashboard.py b/tuskar_ui/infrastructure/dashboard.py index 23b61863..311ba525 100644 --- a/tuskar_ui/infrastructure/dashboard.py +++ b/tuskar_ui/infrastructure/dashboard.py @@ -17,11 +17,71 @@ from django.utils.translation import ugettext_lazy as _ # noqa import horizon +class InfrastructureOverview(horizon.PanelGroup): + slug = "infrastructure_overview" + name = _("Overview") + panels = ( + 'overview', + ) + + +class Deployment(horizon.PanelGroup): + slug = "deploy" + name = _("Deployment") + panels = ( + 'deploy_overview', + 'deploy_controller', + 'deploy_compute', + 'deploy_object_storage', + 'deploy_block_storage', + ) + + +class Resources(horizon.PanelGroup): + slug = "nodes" + name = _("Resources") + panels = ( + 'resources_overview', + 'resources_resource', + 'resources_management', + 'resources_unallocated', + 'resources_archived', + ) + + +class Networks(horizon.PanelGroup): + slug = "networks" + name = _("Networks") + panels = ( + 'networks_overview', + ) + + +class Images(horizon.PanelGroup): + slug = "images" + name = _("Images") + panels = ( + 'images_overview', + ) + + +class Logs(horizon.PanelGroup): + slug = "logs" + name = _("Logs") + panels = ( + 'logs_overview', + ) + + class Infrastructure(horizon.Dashboard): name = _("Infrastructure") slug = "infrastructure" - panels = ('resource_management',) - default_panel = 'resource_management' + panels = ( + InfrastructureOverview, + Deployment, + Resources, + ) + default_panel = 'overview' permissions = ('openstack.roles.admin',) diff --git a/tuskar_ui/infrastructure/resource_management/__init__.py b/tuskar_ui/infrastructure/deploy_block_storage/__init__.py index e69de29b..e69de29b 100644 --- a/tuskar_ui/infrastructure/resource_management/__init__.py +++ b/tuskar_ui/infrastructure/deploy_block_storage/__init__.py diff --git a/tuskar_ui/infrastructure/deploy_block_storage/panel.py b/tuskar_ui/infrastructure/deploy_block_storage/panel.py new file mode 100644 index 00000000..780e5340 --- /dev/null +++ b/tuskar_ui/infrastructure/deploy_block_storage/panel.py @@ -0,0 +1,27 @@ +# -*- 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 _ # noqa + +import horizon + +from tuskar_ui.infrastructure import dashboard + + +class BlockStorage(horizon.Panel): + name = _("Block Storage") + slug = "deploy_block_storage" + + +dashboard.Infrastructure.register(BlockStorage) diff --git a/tuskar_ui/infrastructure/service_management/urls.py b/tuskar_ui/infrastructure/deploy_block_storage/urls.py index 23dcbd5f..79685177 100644 --- a/tuskar_ui/infrastructure/service_management/urls.py +++ b/tuskar_ui/infrastructure/deploy_block_storage/urls.py @@ -1,4 +1,4 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# -*- 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 @@ -14,7 +14,7 @@ from django.conf.urls import defaults -from tuskar_ui.infrastructure.service_management import views +from tuskar_ui.infrastructure.deploy_block_storage import views urlpatterns = defaults.patterns( diff --git a/tuskar_ui/infrastructure/deploy_block_storage/views.py b/tuskar_ui/infrastructure/deploy_block_storage/views.py new file mode 100644 index 00000000..f046b626 --- /dev/null +++ b/tuskar_ui/infrastructure/deploy_block_storage/views.py @@ -0,0 +1,18 @@ +# -*- 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' diff --git a/tuskar_ui/infrastructure/resource_management/flavors/__init__.py b/tuskar_ui/infrastructure/deploy_compute/__init__.py index e69de29b..e69de29b 100644 --- a/tuskar_ui/infrastructure/resource_management/flavors/__init__.py +++ b/tuskar_ui/infrastructure/deploy_compute/__init__.py diff --git a/tuskar_ui/infrastructure/deploy_compute/panel.py b/tuskar_ui/infrastructure/deploy_compute/panel.py new file mode 100644 index 00000000..d7d3d576 --- /dev/null +++ b/tuskar_ui/infrastructure/deploy_compute/panel.py @@ -0,0 +1,27 @@ +# -*- 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 _ # noqa + +import horizon + +from tuskar_ui.infrastructure import dashboard + + +class Compute(horizon.Panel): + name = _("Compute") + slug = "deploy_compute" + + +dashboard.Infrastructure.register(Compute) diff --git a/tuskar_ui/infrastructure/service_management/tests.py b/tuskar_ui/infrastructure/deploy_compute/urls.py index e0f8c290..983c24ae 100644 --- a/tuskar_ui/infrastructure/service_management/tests.py +++ b/tuskar_ui/infrastructure/deploy_compute/urls.py @@ -1,4 +1,4 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# -*- 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 @@ -12,10 +12,12 @@ # License for the specific language governing permissions and limitations # under the License. -from openstack_dashboard.test import helpers as test +from django.conf.urls import defaults +from tuskar_ui.infrastructure.deploy_compute import views -class Service_ManagementTests(test.TestCase): - # Unit tests for service_management. - def test_me(self): - self.assertTrue(1 + 1 == 2) + +urlpatterns = defaults.patterns( + '', + defaults.url(r'^$', views.IndexView.as_view(), name='index'), +) diff --git a/tuskar_ui/infrastructure/deploy_compute/views.py b/tuskar_ui/infrastructure/deploy_compute/views.py new file mode 100644 index 00000000..f046b626 --- /dev/null +++ b/tuskar_ui/infrastructure/deploy_compute/views.py @@ -0,0 +1,18 @@ +# -*- 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' diff --git a/tuskar_ui/infrastructure/resource_management/nodes/__init__.py b/tuskar_ui/infrastructure/deploy_controller/__init__.py index e69de29b..e69de29b 100644 --- a/tuskar_ui/infrastructure/resource_management/nodes/__init__.py +++ b/tuskar_ui/infrastructure/deploy_controller/__init__.py diff --git a/tuskar_ui/infrastructure/deploy_controller/panel.py b/tuskar_ui/infrastructure/deploy_controller/panel.py new file mode 100644 index 00000000..90ba46d6 --- /dev/null +++ b/tuskar_ui/infrastructure/deploy_controller/panel.py @@ -0,0 +1,27 @@ +# -*- 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 _ # noqa + +import horizon + +from tuskar_ui.infrastructure import dashboard + + +class Controller(horizon.Panel): + name = _("Controller") + slug = "deploy_controller" + + +dashboard.Infrastructure.register(Controller) diff --git a/tuskar_ui/infrastructure/service_management/views.py b/tuskar_ui/infrastructure/deploy_controller/urls.py index 6c0c027a..ab9a548d 100644 --- a/tuskar_ui/infrastructure/service_management/views.py +++ b/tuskar_ui/infrastructure/deploy_controller/urls.py @@ -1,4 +1,4 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# -*- 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 @@ -12,13 +12,12 @@ # License for the specific language governing permissions and limitations # under the License. -from horizon import views +from django.conf.urls import defaults +from tuskar_ui.infrastructure.deploy_controller import views -class IndexView(views.APIView): - # A very simple class-based view... - template_name = 'infrastructure/service_management/index.html' - def get_data(self, request, context, *args, **kwargs): - # Add data to the context here... - return context +urlpatterns = defaults.patterns( + '', + defaults.url(r'^$', views.IndexView.as_view(), name='index'), +) diff --git a/tuskar_ui/infrastructure/deploy_controller/views.py b/tuskar_ui/infrastructure/deploy_controller/views.py new file mode 100644 index 00000000..f046b626 --- /dev/null +++ b/tuskar_ui/infrastructure/deploy_controller/views.py @@ -0,0 +1,18 @@ +# -*- 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' diff --git a/tuskar_ui/infrastructure/resource_management/racks/__init__.py b/tuskar_ui/infrastructure/deploy_object_storage/__init__.py index e69de29b..e69de29b 100644 --- a/tuskar_ui/infrastructure/resource_management/racks/__init__.py +++ b/tuskar_ui/infrastructure/deploy_object_storage/__init__.py diff --git a/tuskar_ui/infrastructure/deploy_object_storage/panel.py b/tuskar_ui/infrastructure/deploy_object_storage/panel.py new file mode 100644 index 00000000..95bf4f49 --- /dev/null +++ b/tuskar_ui/infrastructure/deploy_object_storage/panel.py @@ -0,0 +1,27 @@ +# -*- 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 _ # noqa + +import horizon + +from tuskar_ui.infrastructure import dashboard + + +class ObjectStorage(horizon.Panel): + name = _("Object Storage") + slug = "deploy_object_storage" + + +dashboard.Infrastructure.register(ObjectStorage) diff --git a/tuskar_ui/infrastructure/resource_management/flavors/urls.py b/tuskar_ui/infrastructure/deploy_object_storage/urls.py index 18bd85fd..882e9e56 100644 --- a/tuskar_ui/infrastructure/resource_management/flavors/urls.py +++ b/tuskar_ui/infrastructure/deploy_object_storage/urls.py @@ -1,5 +1,4 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - +# -*- 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 @@ -15,15 +14,10 @@ from django.conf.urls import defaults -from tuskar_ui.infrastructure.resource_management.flavors import views - +from tuskar_ui.infrastructure.deploy_object_storage import views -VIEW_MOD = 'tuskar_ui.infrastructure.' \ - 'resource_management.flavors.views' urlpatterns = defaults.patterns( - VIEW_MOD, - defaults.url(r'^(?P<flavor_id>[^/]+)/$', - views.DetailView.as_view(), - name='detail') + '', + defaults.url(r'^$', views.IndexView.as_view(), name='index'), ) diff --git a/tuskar_ui/infrastructure/deploy_object_storage/views.py b/tuskar_ui/infrastructure/deploy_object_storage/views.py new file mode 100644 index 00000000..f046b626 --- /dev/null +++ b/tuskar_ui/infrastructure/deploy_object_storage/views.py @@ -0,0 +1,18 @@ +# -*- 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' diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/__init__.py b/tuskar_ui/infrastructure/deploy_overview/__init__.py index e69de29b..e69de29b 100644 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/__init__.py +++ b/tuskar_ui/infrastructure/deploy_overview/__init__.py diff --git a/tuskar_ui/infrastructure/resource_management/panel.py b/tuskar_ui/infrastructure/deploy_overview/panel.py index 6d302f85..8761cadb 100644 --- a/tuskar_ui/infrastructure/resource_management/panel.py +++ b/tuskar_ui/infrastructure/deploy_overview/panel.py @@ -19,9 +19,9 @@ import horizon from tuskar_ui.infrastructure import dashboard -class Resource_Management(horizon.Panel): - name = _("Resource Management") - slug = "resource_management" +class DeploymentOverview(horizon.Panel): + name = _("Overview") + slug = "deploy_overview" -dashboard.Infrastructure.register(Resource_Management) +dashboard.Infrastructure.register(DeploymentOverview) diff --git a/tuskar_ui/infrastructure/deploy_overview/urls.py b/tuskar_ui/infrastructure/deploy_overview/urls.py new file mode 100644 index 00000000..b98691d3 --- /dev/null +++ b/tuskar_ui/infrastructure/deploy_overview/urls.py @@ -0,0 +1,23 @@ +# -*- 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.deploy_overview import views + + +urlpatterns = defaults.patterns( + '', + defaults.url(r'^$', views.IndexView.as_view(), name='index'), +) diff --git a/tuskar_ui/infrastructure/deploy_overview/views.py b/tuskar_ui/infrastructure/deploy_overview/views.py new file mode 100644 index 00000000..f046b626 --- /dev/null +++ b/tuskar_ui/infrastructure/deploy_overview/views.py @@ -0,0 +1,18 @@ +# -*- 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' diff --git a/tuskar_ui/infrastructure/service_management/__init__.py b/tuskar_ui/infrastructure/images_overview/__init__.py index e69de29b..e69de29b 100644 --- a/tuskar_ui/infrastructure/service_management/__init__.py +++ b/tuskar_ui/infrastructure/images_overview/__init__.py diff --git a/tuskar_ui/infrastructure/images_overview/panel.py b/tuskar_ui/infrastructure/images_overview/panel.py new file mode 100644 index 00000000..ff391346 --- /dev/null +++ b/tuskar_ui/infrastructure/images_overview/panel.py @@ -0,0 +1,27 @@ +# -*- 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 _ # noqa + +import horizon + +from tuskar_ui.infrastructure import dashboard + + +class ImagesOverview(horizon.Panel): + name = _("Overview") + slug = "images_overview" + + +dashboard.Infrastructure.register(ImagesOverview) diff --git a/tuskar_ui/infrastructure/images_overview/urls.py b/tuskar_ui/infrastructure/images_overview/urls.py new file mode 100644 index 00000000..71000913 --- /dev/null +++ b/tuskar_ui/infrastructure/images_overview/urls.py @@ -0,0 +1,23 @@ +# -*- 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.images_overview import views + + +urlpatterns = defaults.patterns( + '', + defaults.url(r'^$', views.IndexView.as_view(), name='index'), +) diff --git a/tuskar_ui/infrastructure/images_overview/views.py b/tuskar_ui/infrastructure/images_overview/views.py new file mode 100644 index 00000000..f046b626 --- /dev/null +++ b/tuskar_ui/infrastructure/images_overview/views.py @@ -0,0 +1,18 @@ +# -*- 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' diff --git a/tuskar_ui/infrastructure/logs_overview/__init__.py b/tuskar_ui/infrastructure/logs_overview/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tuskar_ui/infrastructure/logs_overview/__init__.py diff --git a/tuskar_ui/infrastructure/logs_overview/panel.py b/tuskar_ui/infrastructure/logs_overview/panel.py new file mode 100644 index 00000000..1effb660 --- /dev/null +++ b/tuskar_ui/infrastructure/logs_overview/panel.py @@ -0,0 +1,27 @@ +# -*- 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 _ # noqa + +import horizon + +from tuskar_ui.infrastructure import dashboard + + +class LogsOverview(horizon.Panel): + name = _("Overview") + slug = "logs_overview" + + +dashboard.Infrastructure.register(LogsOverview) diff --git a/tuskar_ui/infrastructure/logs_overview/urls.py b/tuskar_ui/infrastructure/logs_overview/urls.py new file mode 100644 index 00000000..05d7bfda --- /dev/null +++ b/tuskar_ui/infrastructure/logs_overview/urls.py @@ -0,0 +1,23 @@ +# -*- 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.logs_overview import views + + +urlpatterns = defaults.patterns( + '', + defaults.url(r'^$', views.IndexView.as_view(), name='index'), +) diff --git a/tuskar_ui/infrastructure/logs_overview/views.py b/tuskar_ui/infrastructure/logs_overview/views.py new file mode 100644 index 00000000..f046b626 --- /dev/null +++ b/tuskar_ui/infrastructure/logs_overview/views.py @@ -0,0 +1,18 @@ +# -*- 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' diff --git a/tuskar_ui/infrastructure/networks_overview/__init__.py b/tuskar_ui/infrastructure/networks_overview/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tuskar_ui/infrastructure/networks_overview/__init__.py diff --git a/tuskar_ui/infrastructure/networks_overview/panel.py b/tuskar_ui/infrastructure/networks_overview/panel.py new file mode 100644 index 00000000..30f63c78 --- /dev/null +++ b/tuskar_ui/infrastructure/networks_overview/panel.py @@ -0,0 +1,27 @@ +# -*- 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 _ # noqa + +import horizon + +from tuskar_ui.infrastructure import dashboard + + +class NetworksOverview(horizon.Panel): + name = _("Overview") + slug = "networks_overview" + + +dashboard.Infrastructure.register(NetworksOverview) diff --git a/tuskar_ui/infrastructure/networks_overview/urls.py b/tuskar_ui/infrastructure/networks_overview/urls.py new file mode 100644 index 00000000..a80bae82 --- /dev/null +++ b/tuskar_ui/infrastructure/networks_overview/urls.py @@ -0,0 +1,23 @@ +# -*- 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.networks_overview import views + + +urlpatterns = defaults.patterns( + '', + defaults.url(r'^$', views.IndexView.as_view(), name='index'), +) diff --git a/tuskar_ui/infrastructure/networks_overview/views.py b/tuskar_ui/infrastructure/networks_overview/views.py new file mode 100644 index 00000000..f046b626 --- /dev/null +++ b/tuskar_ui/infrastructure/networks_overview/views.py @@ -0,0 +1,18 @@ +# -*- 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' diff --git a/tuskar_ui/infrastructure/overview/panel.py b/tuskar_ui/infrastructure/overview/panel.py index 6d150eb7..cd20476f 100644 --- a/tuskar_ui/infrastructure/overview/panel.py +++ b/tuskar_ui/infrastructure/overview/panel.py @@ -16,10 +16,12 @@ from django.utils.translation import ugettext_lazy as _ # noqa import horizon +from tuskar_ui.infrastructure import dashboard + class Overview(horizon.Panel): name = _("Overview") slug = "overview" -#dashboard.Infrastructure.register(Overview) +dashboard.Infrastructure.register(Overview) diff --git a/tuskar_ui/infrastructure/resource_management/flavors/forms.py b/tuskar_ui/infrastructure/resource_management/flavors/forms.py deleted file mode 100644 index 92065723..00000000 --- a/tuskar_ui/infrastructure/resource_management/flavors/forms.py +++ /dev/null @@ -1,80 +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.forms import formsets -from django.utils import datastructures -from django.utils.translation import ugettext_lazy as _ # noqa - -from horizon import forms - -from tuskar_ui import forms as tuskar_forms - - -CAPACITIES = datastructures.SortedDict([ - # (name, (label, unit, required)), - ('cpu', (_('VCPU'), '', True)), - ('memory', (_('RAM (MB)'), 'MB', True)), - ('storage', (_('Root Disk (GB)'), 'GB', True)), - ('ephemeral_disk', (_('Ephemeral Disk (GB)'), 'GB', False)), - ('swap_disk', (_('Swap Disk (GB)'), 'GB', False)), -]) - - -class FlavorForm(forms.Form): - id = forms.IntegerField(widget=forms.HiddenInput(), required=False) - name = forms.RegexField(label=_("Name"), - max_length=25, - regex=r'^[\w\.\- ]+$', - error_messages={'invalid': _( - 'Name may only ' - 'contain letters, numbers, underscores, ' - 'periods and hyphens.')}, - widget=forms.TextInput(attrs={ - 'class': 'input input-small', - })) - - def __init__(self, *args, **kwargs): - super(FlavorForm, self).__init__(*args, **kwargs) - - for name, (label, unit, required) in CAPACITIES.items(): - self.fields[name] = forms.IntegerField( - label=label, - min_value=0, - required=required, - widget=tuskar_forms.NumberInput(attrs={ - 'class': 'input number_input_slim', - })) - - -class BaseFlavorFormSet(formsets.BaseFormSet): - def clean(self): - if any(self.errors): - # Don't bother validating the formset unless each form is valid - # on its own - return - names = {} - for form in self.forms: - name = form.cleaned_data.get('name') - if not name: - continue - if name in names: - message = _("This value repeats, but it should be unique.") - other_form = names[name] - form._errors['name'] = form.error_class([message]) - other_form._errors['name'] = other_form.error_class([message]) - names[name] = form - - -FlavorFormset = formsets.formset_factory(FlavorForm, extra=1, can_delete=True, - formset=BaseFlavorFormSet) diff --git a/tuskar_ui/infrastructure/resource_management/flavors/tabs.py b/tuskar_ui/infrastructure/resource_management/flavors/tabs.py deleted file mode 100644 index e56cbab2..00000000 --- a/tuskar_ui/infrastructure/resource_management/flavors/tabs.py +++ /dev/null @@ -1,35 +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 _ # noqa - -from horizon import tabs - - -class OverviewTab(tabs.Tab): - name = _("Overview") - slug = "flavor_overview_tab" - template_name = ("infrastructure/resource_management/flavors/" - "_detail_overview.html") - preload = False - - def get_context_data(self, request): - return {"flavor": self.tab_group.kwargs['flavor'], - 'resource_class': self.tab_group.kwargs['resource_class']} - - -class FlavorDetailTabs(tabs.TabGroup): - slug = "flavor_detail_tabs" - tabs = (OverviewTab,) - sticky = True diff --git a/tuskar_ui/infrastructure/resource_management/flavors/tests.py b/tuskar_ui/infrastructure/resource_management/flavors/tests.py deleted file mode 100644 index 13af7bdb..00000000 --- a/tuskar_ui/infrastructure/resource_management/flavors/tests.py +++ /dev/null @@ -1,69 +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.core import urlresolvers -from django import http -import mox - -from tuskar_ui import api as tuskar -from tuskar_ui.test import helpers as test - - -class FlavorsTests(test.BaseAdminViewTests): - - @test.create_stubs({tuskar.Flavor: ('get',), - tuskar.ResourceClass: ('get',)}) - def test_detail_flavor(self): - flavor = self.tuskar_flavors.list()[1] - resource_class = self.tuskar_resource_classes.first() - - tuskar.ResourceClass.get(mox.IsA(http.HttpRequest), - resource_class.id).AndReturn(resource_class) - - tuskar.Flavor.get(mox.IsA(http.HttpRequest), - resource_class.id, - flavor.id).AndReturn(flavor) - - self.mox.ReplayAll() - - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:resource_classes:' - 'flavors:detail', - args=[resource_class.id, flavor.id]) - res = self.client.get(url) - self.assertTemplateUsed(res, - 'infrastructure/resource_management/' - 'flavors/detail.html') - - @test.create_stubs({tuskar.Flavor: ('get',)}) - def test_detail_flavor_exception(self): - flavor = self.tuskar_flavors.list()[1] - resource_class = self.tuskar_resource_classes.first() - - tuskar.Flavor.get(mox.IsA(http.HttpRequest), - resource_class.id, - flavor.id).AndRaise(self.exceptions.tuskar) - - self.mox.ReplayAll() - - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:resource_classes:' - 'flavors:detail', - args=[resource_class.id, flavor.id]) - res = self.client.get(url) - - self.assertRedirectsNoFollow( - res, - urlresolvers.reverse('horizon:infrastructure:resource_management:' - 'index')) diff --git a/tuskar_ui/infrastructure/resource_management/flavors/views.py b/tuskar_ui/infrastructure/resource_management/flavors/views.py deleted file mode 100644 index 8d033544..00000000 --- a/tuskar_ui/infrastructure/resource_management/flavors/views.py +++ /dev/null @@ -1,75 +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.core import urlresolvers -from django.utils.translation import ugettext_lazy as _ # noqa - -from horizon import exceptions -from horizon import tabs as horizon_tabs - -from tuskar_ui import api as tuskar -from tuskar_ui.infrastructure.resource_management.flavors import tabs - - -class DetailView(horizon_tabs.TabView): - tab_group_class = tabs.FlavorDetailTabs - template_name = ('infrastructure/resource_management/flavors/detail.html') - - def get_context_data(self, **kwargs): - context = super(DetailView, self).get_context_data(**kwargs) - context["flavor"] = self.get_flavor_data() - context["resource_class"] = self.get_resource_class_data() - return context - - def get_flavor_data(self): - if not hasattr(self, "_flavor"): - try: - flavor_id = self.kwargs['flavor_id'] - resource_class_id = self.kwargs['resource_class_id'] - flavor = tuskar.Flavor.get( - self.request, resource_class_id, flavor_id) - except Exception: - redirect = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index') - exceptions.handle(self.request, - _('Unable to retrieve details for ' - 'flavor "%s".') % flavor_id, - redirect=redirect) - self._flavor = flavor - return self._flavor - - def get_resource_class_data(self): - if not hasattr(self, "_resource_class"): - try: - resource_class_id = self.kwargs['resource_class_id'] - resource_class = tuskar.ResourceClass.get(self.request, - resource_class_id) - except Exception: - redirect = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index') - exceptions.handle(self.request, - _('Unable to retrieve details for resource ' - 'class "%s".') % resource_class_id, - redirect=redirect) - self._resource_class = resource_class - return self._resource_class - - def get_tabs(self, request, *args, **kwargs): - flavor = self.get_flavor_data() - resource_class = self.get_resource_class_data() - return self.tab_group_class(request, - flavor=flavor, - resource_class=resource_class, - **kwargs) diff --git a/tuskar_ui/infrastructure/resource_management/forms.py b/tuskar_ui/infrastructure/resource_management/forms.py deleted file mode 100644 index 5f80d1f7..00000000 --- a/tuskar_ui/infrastructure/resource_management/forms.py +++ /dev/null @@ -1,33 +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 _ # noqa - -from horizon import exceptions -from horizon import forms -from horizon import messages - -from tuskar_ui import api as tuskar - - -class Provision(forms.SelfHandlingForm): - def handle(self, request, data): - try: - tuskar.Rack.provision_all(request) - except Exception: - exceptions.handle(request, _("Unable to start provisioning.")) - else: - msg = _('Started provisioning.') - messages.success(request, msg) - return True diff --git a/tuskar_ui/infrastructure/resource_management/nodes/forms.py b/tuskar_ui/infrastructure/resource_management/nodes/forms.py deleted file mode 100644 index 68b5566e..00000000 --- a/tuskar_ui/infrastructure/resource_management/nodes/forms.py +++ /dev/null @@ -1,98 +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. - -import django.forms -from django.utils.translation import ugettext_lazy as _ # noqa - -import tuskar_ui.forms - - -class NodeForm(django.forms.Form): - id = django.forms.IntegerField( - required=False, - widget=django.forms.HiddenInput()) - - service_host = django.forms.CharField( - label=_("Service Host"), - widget=django.forms.TextInput(attrs={'class': 'input input-mini'}), - required=True) - mac_address = tuskar_ui.forms.MACField( - label=_("MAC Address"), - widget=django.forms.TextInput(attrs={'class': 'input input-mini'}), - required=True) - - # Hardware Specifications - cpus = django.forms.IntegerField( - label=_("CPUs"), required=True, - min_value=1, widget=tuskar_ui.forms.NumberInput(attrs={ - 'class': 'input number_input_slim', - })) - memory_mb = django.forms.IntegerField( - label=_("Memory"), required=True, min_value=1, - widget=tuskar_ui.forms.NumberInput(attrs={ - 'class': 'input number_input_slim', - })) - local_gb = django.forms.IntegerField( - label=_("Local Disk (GB)"), min_value=1, - widget=tuskar_ui.forms.NumberInput(attrs={ - 'class': 'input number_input_slim', - }), required=True) - - # Power Management - pm_address = django.forms.GenericIPAddressField( - widget=django.forms.TextInput(attrs={'class': 'input input-mini'}), - label=_("Power Management IP"), required=False) - pm_user = django.forms.CharField( - label=_("Power Management User"), - widget=django.forms.TextInput(attrs={'class': 'input input-mini'}), - required=False) - pm_password = django.forms.CharField( - label=_("Power Management Password"), - required=False, widget=django.forms.PasswordInput( - render_value=False, - attrs={'class': 'input input-mini'})) - - # Access - terminal_port = django.forms.IntegerField( - label=_("Terminal Port"), - required=False, min_value=0, max_value=1024, - widget=tuskar_ui.forms.NumberInput(attrs={ - 'class': 'input number_input_slim', - })) - - -class BaseNodeFormSet(django.forms.formsets.BaseFormSet): - def clean(self): - if any(self.errors): - # Don't bother validating the formset unless each form is valid - # on its own - return - unique_fields = ('mac_address', 'pm_address') - values = dict((field, {}) for field in unique_fields) - for form in self.forms: - for field in unique_fields: - value = form.cleaned_data.get(field) - if not value: - continue - if value in values[field]: - message = _("This value repeats, but it should be unique.") - other_form = values[field][value] - form._errors[field] = form.error_class([message]) - other_form._errors[field] = other_form.error_class( - [message]) - values[field][value] = form - - -NodeFormset = django.forms.formsets.formset_factory( - NodeForm, extra=1, can_delete=True, formset=BaseNodeFormSet) diff --git a/tuskar_ui/infrastructure/resource_management/nodes/tables.py b/tuskar_ui/infrastructure/resource_management/nodes/tables.py deleted file mode 100644 index 9ea5d1f5..00000000 --- a/tuskar_ui/infrastructure/resource_management/nodes/tables.py +++ /dev/null @@ -1,104 +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 _ # noqa - -from horizon import exceptions -from horizon import tables - -from tuskar_ui import api as tuskar -from tuskar_ui.infrastructure.resource_management.nodes import forms \ - as nodes_forms -import tuskar_ui.tables - - -class DeleteNodes(tables.DeleteAction): - data_type_singular = _("Node") - data_type_plural = _("Nodes") - - def delete(self, request, obj_id): - try: - baremetal_node = tuskar.BaremetalNode.get(request, obj_id) - baremetal_node.tuskar_node.remove_from_rack(request) - except Exception: - exceptions.handle(request, _("Error deleting node.")) - return False - - -class NodesFilterAction(tables.FilterAction): - def filter(self, table, nodes, filter_string): - """Naive case-insensitive search.""" - q = filter_string.lower() - # This is used both for Tuskar and Baremetal nodes. - return [node for node in nodes if q in node.name.lower()] - - -class NodesTable(tables.DataTable): - service_host = tables.Column( - "service_host", - verbose_name=_("Service Host"), - link=("horizon:infrastructure:resource_management:nodes:detail")) - mac_address = tables.Column("mac_address", verbose_name=_("MAC Address")) - pm_address = tables.Column("pm_address", - verbose_name=_("Management Address")) - status = tables.Column("status", verbose_name=_("Status")) - usage = tables.Column("usage", verbose_name=_("Usage")) - - class Meta: - name = "nodes_table" - verbose_name = _("Nodes") - table_actions = (DeleteNodes, NodesFilterAction) - row_actions = (DeleteNodes,) - - def get_object_display(self, datum): - return datum.service_host - - -class UnrackedNodesTable(NodesTable): - - class Meta: - name = "unracked_nodes" - verbose_name = _("Unracked Nodes") - table_actions = () - row_actions = () - - -class NodesFormsetTable(tuskar_ui.tables.FormsetDataTable): - service_host = tables.Column('service_host', - verbose_name=_("Service Host")) - mac_address = tables.Column('mac_address', verbose_name=_("MAC Address")) - - cpus = tables.Column('cpus', verbose_name=_("CPUs")) - memory_mb = tables.Column('memory_mb', verbose_name=_("Memory (MB)")) - local_gb = tables.Column('local_gb', verbose_name=_("Local Disk (GB)")) - - pm_address = tables.Column('pm_address', - verbose_name=_("Power Management IP")) - pm_user = tables.Column('pm_user', verbose_name=_("Power Management User")) - pm_password = tables.Column('pm_password', - verbose_name=_("Power Management Password")) - - terminal_port = tables.Column('terminal_port', - verbose_name=_("Terminal Port")) - - # This is needed for the formset with can_delete=True - DELETE = tables.Column('DELETE', verbose_name=_("Delete")) - - formset_class = nodes_forms.NodeFormset - - class Meta: - name = "nodes" - verbose_name = _("Nodes") - table_actions = () - multi_select = False diff --git a/tuskar_ui/infrastructure/resource_management/nodes/tabs.py b/tuskar_ui/infrastructure/resource_management/nodes/tabs.py deleted file mode 100644 index 8359da53..00000000 --- a/tuskar_ui/infrastructure/resource_management/nodes/tabs.py +++ /dev/null @@ -1,56 +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 _ # noqa - -from horizon import messages -from horizon import tabs -import novaclient -import requests - - -class OverviewTab(tabs.Tab): - name = _("Overview") - slug = "node_overview_tab" - template_name = ("infrastructure/resource_management/nodes/" - "_detail_overview.html") - preload = False - - def get_context_data(self, request): - baremetal_node = self.tab_group.kwargs['baremetal_node'] - tuskar_node = baremetal_node.tuskar_node - if tuskar_node: - try: - running_instances = len(tuskar_node.running_virtual_machines) - except (requests.exceptions.ConnectionError, - novaclient.exceptions.Unauthorized): - running_instances = _("Unknown") - messages.warning( - request, - _("Can't retrieve the running instances" - "from the overcloud.")) - else: - running_instances = _("None") - - return { - 'baremetal_node': baremetal_node, - 'tuskar_node': tuskar_node, - 'running_instances': running_instances, - } - - -class NodeDetailTabs(tabs.TabGroup): - slug = "node_detail_tabs" - tabs = (OverviewTab,) - sticky = True diff --git a/tuskar_ui/infrastructure/resource_management/nodes/tests.py b/tuskar_ui/infrastructure/resource_management/nodes/tests.py deleted file mode 100644 index 0f059d26..00000000 --- a/tuskar_ui/infrastructure/resource_management/nodes/tests.py +++ /dev/null @@ -1,91 +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.core import urlresolvers -from django import http - -import mox - -from tuskar_ui import api as tuskar -from tuskar_ui.test import helpers as test - - -class NodeViewTests(test.BaseAdminViewTests): - unracked_page = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:nodes:unracked') - - @test.create_stubs({tuskar.BaremetalNode: ('list_unracked',), }) - def test_unracked(self): - unracked_baremetal_nodes = self.baremetal_unracked_nodes.list() - - tuskar.BaremetalNode.list_unracked( - mox.IsA(http.HttpRequest)).AndReturn(unracked_baremetal_nodes) - self.mox.ReplayAll() - - res = self.client.get(self.unracked_page) - self.assertTemplateUsed( - res, - 'infrastructure/resource_management/nodes/unracked.html') - - unracked_nodes_table = res.context['unracked_nodes_table'].data - self.assertItemsEqual(unracked_nodes_table, unracked_baremetal_nodes) - - @test.create_stubs({ - tuskar.BaremetalNode: ('get',), - tuskar.TuskarNode: ('list', 'running_virtual_machines', - 'list_flavors'), - tuskar.Rack: ('get',), - }) - def test_detail_node(self): - baremetal_node = self.baremetal_nodes.first() - tuskar_nodes = self.tuskar_nodes.list() - rack = self.tuskar_racks.first() - - tuskar.BaremetalNode.get(mox.IsA(http.HttpRequest), - baremetal_node.id).AndReturn(baremetal_node) - tuskar.TuskarNode.list(None).AndReturn(tuskar_nodes) - tuskar.Rack.get(None, rack.id).AndReturn(rack) - tuskar.BaremetalNode.get(None, - baremetal_node.id).AndReturn(baremetal_node) - self.mox.ReplayAll() - - tuskar.TuskarNode.running_virtual_machines = [] - tuskar.TuskarNode.list_flavors = [] - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:nodes:detail', - args=[baremetal_node.id]) - res = self.client.get(url) - self.assertTemplateUsed( - res, 'infrastructure/resource_management/nodes/detail.html') - - @test.create_stubs({tuskar.BaremetalNode: ('get',)}) - def test_detail_node_exception(self): - baremetal_node = self.baremetal_nodes.first() - - tuskar.BaremetalNode.get( - mox.IsA(http.HttpRequest), - baremetal_node.id).AndRaise(self.exceptions.tuskar) - - self.mox.ReplayAll() - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:nodes:detail', - args=[baremetal_node.id]) - res = self.client.get(url) - - self.assertRedirectsNoFollow( - res, - urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index')) diff --git a/tuskar_ui/infrastructure/resource_management/nodes/urls.py b/tuskar_ui/infrastructure/resource_management/nodes/urls.py deleted file mode 100644 index c714773f..00000000 --- a/tuskar_ui/infrastructure/resource_management/nodes/urls.py +++ /dev/null @@ -1,30 +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.resource_management.nodes import views - - -NODES = r'^(?P<node_id>[^/]+)/%s$' -VIEW_MOD = 'tuskar_ui.infrastructure.resource_management.nodes.views' - - -urlpatterns = defaults.patterns( - VIEW_MOD, - defaults.url(NODES % 'detail', views.DetailView.as_view(), name='detail'), - defaults.url(r'^unracked/$', - views.UnrackedView.as_view(), - name='unracked'), -) diff --git a/tuskar_ui/infrastructure/resource_management/nodes/views.py b/tuskar_ui/infrastructure/resource_management/nodes/views.py deleted file mode 100644 index 99829841..00000000 --- a/tuskar_ui/infrastructure/resource_management/nodes/views.py +++ /dev/null @@ -1,70 +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.core import urlresolvers -from django.utils.translation import ugettext_lazy as _ # noqa - -from horizon import exceptions -from horizon import tables as horizon_tables -from horizon import tabs as horizon_tabs - -from tuskar_ui import api as tuskar -from tuskar_ui.infrastructure.resource_management.nodes import tables -from tuskar_ui.infrastructure.resource_management.nodes import tabs - - -class UnrackedView(horizon_tables.DataTableView): - table_class = tables.UnrackedNodesTable - template_name = 'infrastructure/resource_management/nodes/unracked.html' - - def get_data(self): - try: - baremetal_nodes = tuskar.BaremetalNode.list_unracked(self.request) - except Exception: - baremetal_nodes = [] - exceptions.handle(self.request, - _('Unable to retrieve baremetal nodes.')) - return baremetal_nodes - - -class DetailView(horizon_tabs.TabView): - tab_group_class = tabs.NodeDetailTabs - template_name = 'infrastructure/resource_management/nodes/detail.html' - - def get_context_data(self, **kwargs): - context = super(DetailView, self).get_context_data(**kwargs) - context["baremetal_node"] = self.get_data() - context["tuskar_node"] = self.get_data().tuskar_node - return context - - def get_data(self): - if not hasattr(self, "_baremetal_node"): - baremetal_node_id = self.kwargs['node_id'] - try: - baremetal_node = tuskar.BaremetalNode.get(self.request, - baremetal_node_id) - except Exception: - redirect = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index') - exceptions.handle(self.request, - _('Unable to retrieve details for ' - 'node "%s".') % baremetal_node_id, - redirect=redirect) - self._baremetal_node = baremetal_node - return self._baremetal_node - - def get_tabs(self, request, *args, **kwargs): - baremetal_node = self.get_data() - return self.tab_group_class( - request, baremetal_node=baremetal_node, **kwargs) diff --git a/tuskar_ui/infrastructure/resource_management/racks/forms.py b/tuskar_ui/infrastructure/resource_management/racks/forms.py deleted file mode 100644 index cc25e3fe..00000000 --- a/tuskar_ui/infrastructure/resource_management/racks/forms.py +++ /dev/null @@ -1,153 +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. - -import django.forms -from django.utils.translation import ugettext_lazy as _ # noqa - -from horizon import exceptions -from horizon import forms -from horizon import messages - -from tuskar_ui import api as tuskar - -import base64 -import csv -import logging -import StringIO - -LOG = logging.getLogger(__name__) - - -class UploadRack(forms.SelfHandlingForm): - csv_file = forms.FileField(label=_("Choose CSV File"), - help_text=("CSV file with rack definitions"), - required=False) - uploaded_data = forms.CharField(widget=forms.HiddenInput(), - required=False) - - def clean_csv_file(self): - csv_file = self.cleaned_data['csv_file'] - data = csv_file.read() if csv_file else None - - if 'upload' in self.request.POST: - if not csv_file: - raise django.forms.ValidationError(_('CSV file not set.')) - else: - try: - CSVRack.from_str(data) - except Exception: - LOG.exception("Failed to parse rack CSV file.") - raise django.forms.ValidationError( - _('Failed to parse CSV file.')) - return data - - def clean_uploaded_data(self): - data = self.cleaned_data['uploaded_data'] - if 'add_racks' in self.request.POST: - if not data: - raise django.forms.ValidationError(_('Upload CSV file first')) - elif 'upload' in self.request.POST: - # reset obsolete uploaded data - self.data['uploaded_data'] = None - return data - - def handle(self, request, data): - if 'upload' in self.request.POST: - # if upload button was pressed, stay on the same page - # but show content of the CSV file in table - racks_str = self.cleaned_data['csv_file'] - self.initial['racks'] = CSVRack.from_str(racks_str) - self.data['uploaded_data'] = base64.b64encode(racks_str) - return False - else: - fails = [] - successes = [] - racks_str = self.cleaned_data['uploaded_data'] - racks = CSVRack.from_str(base64.b64decode(racks_str)) - # get the resource class ids by resource class names - rclass_ids = dict((rc.name, rc.id) for rc in - tuskar.ResourceClass.list(request)) - for rack in racks: - try: - tuskar.Rack.create( - request, - name=rack.name, - resource_class_id=rclass_ids[rack.resource_class], - location=rack.region, - subnet=rack.subnet, - ) - # FIXME: will have to handle nodes once proper attributes - # for nodes are added - successes.append(rack.name) - except Exception: - LOG.exception("Exception in processing rack CSV file.") - fails.append(rack.name) - if successes: - messages.success(request, - _('Added %d racks.') % len(successes)) - if fails: - messages.error(request, - _('Failed to add following racks: %s') % - (',').join(fails)) - return True - - -class CSVRack: - def __init__(self, **kwargs): - self.id = kwargs['id'] - self.name = kwargs['name'] - self.resource_class = kwargs['resource_class'] - self.region = kwargs['region'] - self.subnet = kwargs['subnet'] - self.nodes = kwargs['nodes'] - - @classmethod - def from_str(cls, csv_str): - racks = [] - csvreader = csv.reader(StringIO.StringIO(csv_str), delimiter=',') - for row in csvreader: - # ignore empty rows - if not row: - continue - racks.append(cls(id=row[0], - name=row[0], - resource_class=row[1], - subnet=row[2], - region=row[3], - nodes=row[4].split())) - return racks - - def nodes_count(self): - return len(self.nodes) - - -class UpdateRackStatus(forms.SelfHandlingForm): - - def handle(self, request, data): - try: - rack = self.initial.get('rack', None) - action = request.GET.get('action') - rack.state = { - 'start': 'active', - 'unprovision': 'unprovisioned', - 'reboot': 'active', - 'shutdown': 'off', - }[action] - rack = tuskar.Rack.update(request, rack.id, {'state': rack.state}) - except Exception: - exceptions.handle(request, _("Unable to update Rack status.")) - else: - msg = _('Updated rack "%s" status.') % rack.name - messages.success(request, msg) - return True diff --git a/tuskar_ui/infrastructure/resource_management/racks/tables.py b/tuskar_ui/infrastructure/resource_management/racks/tables.py deleted file mode 100644 index 07e05f03..00000000 --- a/tuskar_ui/infrastructure/resource_management/racks/tables.py +++ /dev/null @@ -1,126 +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. - -import logging - -from django.utils.translation import ugettext_lazy as _ # noqa - -from horizon import tables - -from tuskar_ui import api as tuskar - - -LOG = logging.getLogger(__name__) - - -class DeleteRacks(tables.DeleteAction): - data_type_singular = _("Rack") - data_type_plural = _("Racks") - - def delete(self, request, obj_id): - tuskar.Rack.delete(request, obj_id) - - -class CreateRack(tables.LinkAction): - name = "create" - verbose_name = _("Create Rack") - url = "horizon:infrastructure:resource_management:racks:create" - classes = ("ajax-modal", "btn-create") - - -class UploadRack(tables.LinkAction): - name = "upload" - verbose_name = _("Upload Rack") - url = "horizon:infrastructure:resource_management:racks:upload" - classes = ("ajax-modal", "btn-upload") - - -class EditRack(tables.LinkAction): - name = "edit" - verbose_name = _("Edit Rack") - url = "horizon:infrastructure:resource_management:racks:edit" - classes = ("ajax-modal", "btn-edit") - - -class RacksFilterAction(tables.FilterAction): - - def filter(self, table, racks, filter_string): - """Naive case-insensitive search.""" - q = filter_string.lower() - return [rack for rack in racks - if q in rack.name.lower()] - - -class UpdateRow(tables.Row): - ajax = True - - def get_data(self, request, rack_id): - rack = tuskar.Rack.get(request, rack_id) - return rack - - -def _usage_filter(vm_capacity): - if vm_capacity and vm_capacity.value: - return "{0:.0f} %".format( - round((100.0 / vm_capacity.value) * vm_capacity.usage)) - - -class RacksTable(tables.DataTable): - STATUS_CHOICES = ( - ("unprovisioned", False), - ("provisioning", None), - ("active", True), - ("error", False), - ) - name = tables.Column('name', - link=("horizon:infrastructure:resource_management" - ":racks:detail"), - verbose_name=_("Rack Name")) - subnet = tables.Column('subnet', verbose_name=_("IP Subnet")) - resource_class = tables.Column( - 'resource_class', - verbose_name=_("Class"), - filters=(lambda resource_class: getattr(resource_class, 'name', None),) - ) - node_count = tables.Column('nodes_count', verbose_name=_("Nodes")) - state = tables.Column('state', - verbose_name=_("State"), - status=True, - status_choices=STATUS_CHOICES) - - usage = tables.Column( - 'vm_capacity', - verbose_name=_("Usage"), - filters=(_usage_filter,), - ) - - class Meta: - name = "racks" - row_class = UpdateRow - status_columns = ["state"] - verbose_name = _("Racks") - table_actions = (UploadRack, CreateRack, DeleteRacks, - RacksFilterAction) - row_actions = (EditRack, DeleteRacks) - - -class UploadRacksTable(tables.DataTable): - name = tables.Column("name") - subnet = tables.Column("subnet") - nodes_count = tables.Column("nodes_count") - #region = tables.Column("region") - - class Meta: - name = "uploaded_racks" - verbose_name = " " diff --git a/tuskar_ui/infrastructure/resource_management/racks/tabs.py b/tuskar_ui/infrastructure/resource_management/racks/tabs.py deleted file mode 100644 index a474680b..00000000 --- a/tuskar_ui/infrastructure/resource_management/racks/tabs.py +++ /dev/null @@ -1,53 +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 _ # noqa - -from horizon import exceptions -from horizon import tabs - -from tuskar_ui.infrastructure.resource_management.nodes import tables - - -class OverviewTab(tabs.Tab): - name = _("Overview") - slug = "rack_overview_tab" - template_name = ("infrastructure/resource_management/racks/" - "_detail_overview.html") - - def get_context_data(self, request): - return {"rack": self.tab_group.kwargs['rack']} - - -class NodesTab(tabs.TableTab): - table_classes = (tables.NodesTable,) - name = _("Nodes") - slug = "nodes" - template_name = "horizon/common/_detail_table.html" - - def get_nodes_table_data(self): - try: - rack = self.tab_group.kwargs['rack'] - baremetal_nodes = rack.list_baremetal_nodes - except Exception: - baremetal_nodes = [] - exceptions.handle(self.tab_group.request, - _('Unable to retrieve node list.')) - return baremetal_nodes - - -class RackDetailTabs(tabs.TabGroup): - slug = "rack_detail_tabs" - tabs = (OverviewTab, NodesTab) - sticky = True diff --git a/tuskar_ui/infrastructure/resource_management/racks/tests.py b/tuskar_ui/infrastructure/resource_management/racks/tests.py deleted file mode 100644 index 24932ee5..00000000 --- a/tuskar_ui/infrastructure/resource_management/racks/tests.py +++ /dev/null @@ -1,411 +0,0 @@ -# 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 import http - -import mox - -from tuskar_ui import api as tuskar -from tuskar_ui.test import helpers as test - -import base64 -import tempfile - - -class RackViewTests(test.BaseAdminViewTests): - index_page = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index') - - index_page_racks_tab = (urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index') + - "?tab=resource_management_tabs__racks_tab") - - @test.create_stubs({tuskar.ResourceClass: ('list',)}) - def test_create_rack_get(self): - tuskar.ResourceClass.list( - mox.IsA(http.HttpRequest)).AndReturn( - self.tuskar_resource_classes.list()) - - self.mox.ReplayAll() - - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:create') - rack = self.client.get(url) - - self.assertEqual(rack.status_code, 200) - self.assertTemplateUsed(rack, - 'infrastructure/_workflow_base.html') - - # FIXME (mawagner) - After moving EditRack to use workflows, we need - # to circle back and fix these tests. - # - @test.create_stubs({tuskar.Rack: ('list', 'create',), - tuskar.ResourceClass: ('list',), - tuskar.BaremetalNode: ('create',)}) - def test_create_rack_post(self): - baremetal_node = self.baremetal_nodes.first() - - tuskar.Rack.list( - mox.IsA(http.HttpRequest)).AndReturn( - self.tuskar_racks.list()) - tuskar.BaremetalNode.create( - mox.IsA(http.HttpRequest), - service_host='New Node', - cpus=1, - memory_mb=1024, - local_gb=10, - prov_mac_address='AA:BB:CC:DD:EE:FF', - pm_address=u'', - pm_user=u'', - pm_password=u'', - terminal_port=None).AndReturn(baremetal_node) - tuskar.Rack.create( - mox.IsA(http.HttpRequest), - name='New Rack', - resource_class_id=u'1', - location='Tokyo', - subnet='1.2.3.4/24', - baremetal_nodes=[{'id': '11'}]).AndReturn(None) - tuskar.ResourceClass.list( - mox.IsA(http.HttpRequest)).AndReturn( - self.tuskar_resource_classes.list()) - - self.mox.ReplayAll() - - data = { - 'name': 'New Rack', - 'resource_class_id': u'1', - 'location': 'Tokyo', - 'subnet': '1.2.3.4/24', - 'nodes-TOTAL_FORMS': 1, - 'nodes-INITIAL_FORMS': 0, - 'nodes-MAX_NUM_FORMS': 1024, - 'nodes-0-service_host': 'New Node', - 'nodes-0-mac_address': 'aa:bb:cc:dd:ee:ff', - 'nodes-0-cpus': u'1', - 'nodes-0-memory_mb': u'1024', - 'nodes-0-local_gb': u'10', - } - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:create') - resp = self.client.post(url, data) - self.assertRedirectsNoFollow(resp, self.index_page_racks_tab) - - @test.create_stubs({tuskar.Rack: ('get', 'list_tuskar_nodes'), - tuskar.ResourceClass: ('list',)}) - def test_edit_rack_get(self): - rack = self.tuskar_racks.first() - - tuskar.Rack.get( - mox.IsA(http.HttpRequest), rack.id).AndReturn(rack) - tuskar.Rack.list_tuskar_nodes = [] - tuskar.Rack.get(mox.IsA(http.HttpRequest), rack.id).AndReturn(rack) - tuskar.ResourceClass.list( - mox.IsA(http.HttpRequest)).AndReturn( - self.tuskar_resource_classes.list()) - - self.mox.ReplayAll() - - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:edit', args=[1]) - res = self.client.get(url) - self.assertEqual(res.status_code, 200) - self.assertTemplateUsed(res, 'infrastructure/_workflow_base.html') - - @test.create_stubs({ - tuskar.Rack: ('get', 'list', 'update', 'list_tuskar_nodes'), - tuskar.ResourceClass: ('list',), - }) - def test_edit_rack_post(self): - rack = self.tuskar_racks.first() - - rack_data = { - 'name': 'Updated Rack', - 'resource_class_id': u'1', - 'rack_id': u'1', - 'location': 'New Location', - 'subnet': '127.10.10.0/24', - 'baremetal_nodes': [], - } - - data = { - 'name': 'Updated Rack', - 'resource_class_id': u'1', - 'rack_id': u'1', - 'location': 'New Location', - 'subnet': '127.10.10.0/24', - 'nodes-TOTAL_FORMS': 0, - 'nodes-INITIAL_FORMS': 0, - 'nodes-MAX_NUM_FORMS': 1024, - } - - tuskar.Rack.get( - mox.IsA(http.HttpRequest), rack.id).AndReturn(rack) - tuskar.Rack.list_tuskar_nodes = [] - tuskar.Rack.get( - mox.IsA(http.HttpRequest), rack.id).AndReturn(rack) - tuskar.Rack.list( - mox.IsA(http.HttpRequest)).AndReturn( - self.tuskar_racks.list()) - tuskar.Rack.update(mox.IsA(http.HttpRequest), rack.id, rack_data) - tuskar.ResourceClass.list( - mox.IsA(http.HttpRequest)).AndReturn( - self.tuskar_resource_classes.list()) - - self.mox.ReplayAll() - - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:edit', - args=[rack.id]) - response = self.client.post(url, data) - self.assertNoFormErrors(response) - self.assertMessageCount(success=1) - self.assertRedirectsNoFollow(response, self.index_page_racks_tab) - - @test.create_stubs({tuskar.Rack: ('get',)}) - def test_edit_status_rack_get(self): - rack = self.tuskar_racks.first() - - tuskar.Rack.\ - get(mox.IsA(http.HttpRequest), rack.id).\ - AndReturn(rack) - - self.mox.ReplayAll() - - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:edit_status', - args=[rack.id]) - res = self.client.get(url) - self.assertEqual(res.status_code, 200) - self.assertTemplateUsed( - res, - 'infrastructure/resource_management/racks/edit_status.html') - - @test.create_stubs({tuskar.Rack: ('get', 'update')}) - def test_edit_status_update_rack_post(self): - rack = self.tuskar_racks.first() - - tuskar.Rack.\ - get(mox.IsA(http.HttpRequest), rack.id).\ - AndReturn(rack) - tuskar.Rack.update(mox.IsA(http.HttpRequest), rack.id, - {'state': 'active'}).AndReturn(rack) - - self.mox.ReplayAll() - - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:edit_status', - args=[rack.id]) + "?action=start" - response = self.client.post(url) - - self.assertNoFormErrors(response) - self.assertMessageCount(success=1) - self.assertRedirectsNoFollow(response, self.index_page) - - @test.create_stubs({tuskar.Rack: ('delete', 'list')}) - def test_delete_rack(self): - rack_id = u'1' - tuskar.Rack.delete( - mox.IsA(http.HttpRequest), rack_id).AndReturn(None) - tuskar.Rack.list( - mox.IsA(http.HttpRequest)).AndReturn( - self.tuskar_racks.list()) - - self.mox.ReplayAll() - data = {'action': 'racks__delete__%s' % rack_id} - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:index') - result = self.client.post(url, data) - self.assertRedirectsNoFollow(result, self.index_page) - - def test_upload_rack_get(self): - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:upload') - rack = self.client.get(url) - - self.assertEqual(rack.status_code, 200) - self.assertTemplateUsed( - rack, 'infrastructure/resource_management/racks/upload.html') - - def test_upload_rack_upload(self): - csv_data = ('Rack1,rclass1,192.168.111.0/24,regionX,f0:dd:f1:da:f9:b5 ' - 'f2:de:f1:da:f9:66 f2:de:ff:da:f9:67') - temp_file = tempfile.TemporaryFile() - temp_file.write(csv_data) - temp_file.flush() - temp_file.seek(0) - - data = {'csv_file': temp_file, 'upload': '1'} - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:upload') - resp = self.client.post(url, data) - self.assertTemplateUsed( - resp, 'infrastructure/resource_management/racks/upload.html') - self.assertNoFormErrors(resp) - self.assertEqual(resp.context['form']['uploaded_data'].value(), - base64.b64encode(csv_data)) - - def test_upload_rack_upload_with_error(self): - data = {'upload': '1'} - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:upload') - resp = self.client.post(url, data) - self.assertTemplateUsed( - resp, 'infrastructure/resource_management/racks/upload.html') - self.assertFormErrors(resp, 1) - self.assertEqual(resp.context['form']['uploaded_data'].value(), - None) - - @test.create_stubs({tuskar.Rack: ('create',), - tuskar.ResourceClass: ('list',)}) - def test_upload_rack_create(self): - tuskar.Rack.create(mox.IsA(http.HttpRequest), - name='Rack1', - resource_class_id='1', - location='regionX', - subnet='192.168.111.0/24').AndReturn(None) - tuskar.ResourceClass.list( - mox.IsA(http.HttpRequest)).AndReturn( - self.tuskar_resource_classes.list()) - self.mox.ReplayAll() - csv_data = ('Rack1,rclass1,192.168.111.0/24,regionX,f0:dd:f1:da:f9:b5 ' - 'f2:de:f1:da:f9:66 f2:de:ff:da:f9:67') - - data = {'uploaded_data': base64.b64encode(csv_data), 'add_racks': '1'} - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:upload') - resp = self.client.post(url, data) - self.assertRedirectsNoFollow(resp, self.index_page) - self.assertMessageCount(success=1) - self.assertMessageCount(error=0) - - @test.create_stubs({ - tuskar.Rack: ('get', 'list_tuskar_nodes', 'list_flavors'), - tuskar.ResourceClass: ('get',), - }) - def test_detail_rack(self): - rack = self.tuskar_racks.first() - rack.request = self.request - resource_class = self.tuskar_resource_classes.first() - - tuskar.Rack.get(mox.IsA(http.HttpRequest), - rack.id).AndReturn(rack) - tuskar.ResourceClass.get(mox.IsA(http.HttpRequest), - resource_class.id).AndReturn(resource_class) - self.mox.ReplayAll() - - tuskar.Rack.list_tuskar_nodes = [] - tuskar.Rack.list_flavors = [] - - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:detail', - args=[rack.id]) - res = self.client.get(url) - self.assertTemplateUsed(res, "infrastructure/resource_management/" - "racks/detail.html") - - # FIXME: test actual json output once we stop using mock data - def test_usage_data_rack(self): - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:usage_data') - res = self.client.get(url) - self.assertEquals(res['Content-Type'], 'application/json') - - # FIXME: test actual json output once we stop using mock data - @test.create_stubs({tuskar.Rack: ('get',)}) - def test_top_communicating_rack(self): - rack = self.tuskar_racks.first() - - tuskar.Rack.get(mox.IsA(http.HttpRequest), - rack.id).AndReturn(rack) - - self.mox.ReplayAll() - - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:' - 'top_communicating', args=[rack.id]) - res = self.client.get(url) - self.assertEquals(res['Content-Type'], 'application/json') - - # FIXME: test actual json output once we stop using mock data - @test.create_stubs({tuskar.Rack: ('get',)}) - def test_node_health_rack(self): - rack = self.tuskar_racks.first() - - tuskar.Rack.get(mox.IsA(http.HttpRequest), - rack.id).AndReturn(rack) - - self.mox.ReplayAll() - - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:' - 'node_health', args=[rack.id]) - res = self.client.get(url) - self.assertEquals(res['Content-Type'], 'application/json') - - @test.create_stubs({tuskar.Rack: ('get',)}) - def test_check_state_rack(self): - rack = self.tuskar_racks.first() - - tuskar.Rack.get(mox.IsA(http.HttpRequest), - rack.id).AndReturn(rack) - - self.mox.ReplayAll() - - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:racks:' - 'check_state', args=[rack.id]) - res = self.client.get(url) - state_json = '{"state": "active"}' - - self.assertEquals(res['Content-Type'], 'application/json') - self.assertEquals(res.content, state_json) - - @test.create_stubs({ - tuskar.Rack: ('get', 'list_baremetal_nodes', 'update', - 'list_tuskar_nodes'), - tuskar.BaremetalNode: ('get',), - tuskar.TuskarNode: ('list',), - }) - def test_node_delete(self): - rack = self.tuskar_racks.first() - rack.request = self.request - baremetal_nodes = self.baremetal_nodes.list() - baremetal_node = baremetal_nodes[0] - baremetal_node.request = self.request - tuskar_nodes = self.tuskar_nodes.list() - - tuskar.Rack.get(mox.IsA(http.HttpRequest), rack.id).AndReturn(rack) - tuskar.BaremetalNode.get(mox.IsA(http.HttpRequest), - baremetal_node.id).AndReturn(baremetal_node) - tuskar.TuskarNode.list( - mox.IsA(http.HttpRequest)).AndReturn(tuskar_nodes) - tuskar.Rack.get(None, rack.id).AndReturn(rack) # called by node.rack - tuskar.Rack.update(mox.IsA(http.HttpRequest), rack.id, { - 'baremetal_nodes': [{'id': node.id} - for node in baremetal_nodes - if node.id != baremetal_node.id], - }).AndReturn(rack) - - tuskar.Rack.list_baremetal_nodes = baremetal_nodes - tuskar.Rack.list_tuskar_nodes = tuskar_nodes - self.mox.ReplayAll() - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:racks:detail', - args=[rack.id]) - form_data = {'action': 'nodes_table__delete__%s' % baremetal_node.id} - response = self.client.post(url, form_data) - self.assertNoFormErrors(response) - self.assertMessageCount(success=1) - self.assertRedirectsNoFollow(response, url) diff --git a/tuskar_ui/infrastructure/resource_management/racks/urls.py b/tuskar_ui/infrastructure/resource_management/racks/urls.py deleted file mode 100644 index 58a1cf58..00000000 --- a/tuskar_ui/infrastructure/resource_management/racks/urls.py +++ /dev/null @@ -1,43 +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 import urls - -from tuskar_ui.infrastructure.resource_management.racks import views - -RACKS = r'^(?P<rack_id>[^/]+)/%s$' -VIEW_MOD = 'tuskar_ui.infrastructure.resource_management.racks.views' - - -urlpatterns = urls.patterns( - VIEW_MOD, - urls.url(r'^create/$', views.CreateView.as_view(), name='create'), - urls.url(r'^upload/$', views.UploadView.as_view(), name='upload'), - urls.url(r'^usage_data$', - views.UsageDataView.as_view(), - name='usage_data'), - urls.url(RACKS % 'edit/', views.EditView.as_view(), name='edit'), - urls.url(RACKS % 'detail_edit/', - views.DetailEditView.as_view(), - name='detail_edit'), - urls.url(RACKS % 'edit_status/', - views.EditRackStatusView.as_view(), - name='edit_status'), - urls.url(RACKS % 'detail', views.DetailView.as_view(), name='detail'), - urls.url(RACKS % 'top_communicating.json', - 'top_communicating', - name='top_communicating'), - urls.url(RACKS % 'node_health.json', 'node_health', name='node_health'), - urls.url(RACKS % 'check_state.json', 'check_state', name='check_state'), -) diff --git a/tuskar_ui/infrastructure/resource_management/racks/views.py b/tuskar_ui/infrastructure/resource_management/racks/views.py deleted file mode 100644 index d28dbb82..00000000 --- a/tuskar_ui/infrastructure/resource_management/racks/views.py +++ /dev/null @@ -1,250 +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. - -import datetime -import json -import logging -import random - -from django.core.serializers import json as json_serializer -from django.core import urlresolvers -from django import http - -from django.utils import simplejson -from django.utils.translation import ugettext_lazy as _ # noqa -from django.views import generic - -from horizon import exceptions -from horizon import forms as horizon_forms -from horizon import tabs as horizon_tabs - -from tuskar_ui import api as tuskar -from tuskar_ui.infrastructure.resource_management.racks import forms -from tuskar_ui.infrastructure.resource_management.racks import tables -from tuskar_ui.infrastructure.resource_management.racks import tabs -from tuskar_ui.infrastructure.resource_management.racks import workflows -from tuskar_ui import workflows as tuskar_workflows - - -LOG = logging.getLogger(__name__) - - -class CreateView(tuskar_workflows.WorkflowView): - workflow_class = workflows.CreateRack - - def get_initial(self): - pass - - -class UploadView(horizon_forms.ModalFormView): - form_class = forms.UploadRack - template_name = 'infrastructure/resource_management/racks/upload.html' - success_url = urlresolvers.reverse_lazy( - 'horizon:infrastructure:resource_management:index') - - def get_context_data(self, **kwargs): - context = super(UploadView, self).get_context_data(**kwargs) - context['racks_table'] = tables.UploadRacksTable( - self.request, kwargs['form'].initial.get('racks', [])) - return context - - -class EditView(tuskar_workflows.WorkflowView): - workflow_class = workflows.EditRack - - def get_initial(self): - obj = tuskar.Rack.get(self.request, self.kwargs['rack_id']) - # mac_str = "\n".join(x.mac_address for x in obj.list_tuskar_nodes) - return {'name': obj.name, 'resource_class_id': obj.resource_class_id, - 'location': obj.location, 'subnet': obj.subnet, - 'state': obj.state, 'rack_id': self.kwargs['rack_id']} - - -class DetailEditView(EditView): - workflow_class = workflows.DetailEditRack - - -class EditRackStatusView(horizon_forms.ModalFormView): - form_class = forms.UpdateRackStatus - template_name = 'infrastructure/resource_management/racks/edit_status.html' - - def get_success_url(self): - # Redirect to previous url - default_url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index') - return self.request.META.get('HTTP_REFERER', default_url) - - def get_context_data(self, **kwargs): - context = super(EditRackStatusView, self).get_context_data(**kwargs) - context['rack_id'] = self.kwargs['rack_id'] - context['action'] = context['form'].initial.get('action', None) - return context - - def get_initial(self): - try: - rack = tuskar.Rack.get( - self.request, self.kwargs['rack_id']) - action = self.request.GET.get('action') - except Exception: - exceptions.handle(self.request, - _("Unable to retrieve rack data.")) - return {'rack': rack, - 'action': action} - - -class DetailView(horizon_tabs.TabbedTableView): - tab_group_class = tabs.RackDetailTabs - template_name = 'infrastructure/resource_management/racks/detail.html' - - def get_context_data(self, **kwargs): - context = super(DetailView, self).get_context_data(**kwargs) - context["rack"] = self.get_data() - return context - - def get_data(self): - if not hasattr(self, "_rack"): - try: - rack_id = self.kwargs['rack_id'] - rack = tuskar.Rack.get(self.request, rack_id) - except Exception: - redirect = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index') - exceptions.handle( - self.request, - _('Unable to retrieve details for rack "%s".') % rack_id, - redirect=redirect) - self._rack = rack - return self._rack - - def get_tabs(self, request, *args, **kwargs): - rack = self.get_data() - return self.tab_group_class(request, rack=rack, - **kwargs) - - -class UsageDataView(generic.View): - - def get(self, request, *args, **kwargs): - interval = request.GET.get('interval', '1w') - series = request.GET.get('series', "") - series = series.split(',') - - if interval == '12h': - data_count = 12 - timedelta_param = 'hours' - elif interval == '24h': - data_count = 24 - timedelta_param = 'hours' - elif interval == '1m': - data_count = 30 - timedelta_param = 'days' - elif interval == '1y': - data_count = 52 - timedelta_param = 'weeks' - else: - # default is 1 week - data_count = 7 - timedelta_param = 'days' - - values = [] - for i in range(data_count): - timediff = datetime.timedelta(**{timedelta_param: i}) - current_value = {'date': datetime.datetime.now() - timediff} - - for usage_type in series: - current_value[usage_type] = random.randint(1, 9) - - values.append(current_value) - - return http.HttpResponse( - json.dumps(values, cls=json_serializer.DjangoJSONEncoder), - mimetype='application/json') - - -def top_communicating(request, rack_id=None): - # FIXME replace mock data - random.seed() - data = [] - statuses = ["Insane level of communication", - "High level of communication", - "Normal level of communication", - "Low level of communication"] - - rack = tuskar.Rack.get(request, rack_id) - for tuskar_node_id in rack.tuskar_node_ids: - status = random.randint(0, 3) - percentage = random.randint(0, 100) - - tooltip = ("<p>Node: <strong>{0}</strong></p><p>{1}</p>").format( - tuskar_node_id, statuses[status]) - - data.append({'tooltip': tooltip, - 'status': statuses[status], - 'scale': 'linear_color_scale', - 'percentage': percentage, - 'id': "FIXME_RACK id", - 'name': "FIXME name", - 'url': "FIXME url"}) - - data.sort(key=lambda x: x['percentage']) - - # FIXME dynamically set the max domain, based on data - settings = {'scale': 'linear_color_scale', - 'domain': [0, max([datum['percentage'] for datum in data])], - 'range': ["#000060", "#99FFFF"]} - res = {'data': data, - 'settings': settings} - return http.HttpResponse(simplejson.dumps(res), - mimetype="application/json") - - -def node_health(request, rack_id=None): - # FIXME replace mock data - random.seed() - data = [] - statuses = ["Good", "Warnings", "Disaster"] - colors = ["rgb(244,244,244)", "rgb(240,170,0)", "rgb(200,0,0)"] - - rack = tuskar.Rack.get(request, rack_id) - - for tuskar_node_id in rack.tuskar_node_ids: - rand_index = random.randint(0, 2) - percentage = (2 - rand_index) * 50 - color = colors[rand_index] - - tooltip = ("<p>Node: <strong>{0}</strong></p><p>{1}</p>").format( - tuskar_node_id, statuses[rand_index]) - - data.append({'tooltip': tooltip, - 'color': color, - 'status': statuses[rand_index], - 'percentage': percentage, - 'id': tuskar_node_id, - 'name': tuskar_node_id, - 'url': "FIXME url"}) - - data.sort(key=lambda x: x['percentage']) - - res = {'data': data} - return http.HttpResponse(simplejson.dumps(res), - mimetype="application/json") - - -def check_state(request, rack_id=None): - rack = tuskar.Rack.get(request, rack_id) - - res = {'state': rack.state} - - return http.HttpResponse(simplejson.dumps(res), - mimetype="application/json") diff --git a/tuskar_ui/infrastructure/resource_management/racks/workflows.py b/tuskar_ui/infrastructure/resource_management/racks/workflows.py deleted file mode 100644 index cca10bcc..00000000 --- a/tuskar_ui/infrastructure/resource_management/racks/workflows.py +++ /dev/null @@ -1,266 +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.core import urlresolvers -from django.utils.translation import ugettext_lazy as _ # noqa - -from horizon import exceptions -from horizon import forms -from horizon import messages -from horizon import workflows - -import requests - -from tuskar_ui import api as tuskar -from tuskar_ui import forms as tuskar_forms -from tuskar_ui.infrastructure.resource_management.nodes import tables \ - as nodes_tables -import tuskar_ui.workflows - - -class RackCreateInfoAction(workflows.Action): - name = forms.RegexField(label=_("Name"), - max_length=25, - regex=r'^[\w\.\- ]+$', - error_messages={'invalid': _( - 'Name may only ' - 'contain letters, numbers, underscores, ' - 'periods and hyphens.')}) - location = forms.CharField(label=_("Location")) - subnet = tuskar_forms.NetworkField(label=_("IP Subnet")) - resource_class_id = forms.ChoiceField(label=_("Resource Class")) - - def clean(self): - cleaned_data = super(RackCreateInfoAction, self).clean() - name = cleaned_data.get('name') - rack_id = self.initial.get('rack_id', None) - subnet = cleaned_data.get('subnet') - try: - racks = tuskar.Rack.list(self.request) - except Exception: - racks = [] - exceptions.check_message(['Connection', 'refused'], - _("Unable to retrieve rack list.")) - raise - - # Validations: detect duplicates - for rack in racks: - other_record = rack_id != rack.id - if rack.name == name and other_record: - raise forms.ValidationError( - _('The name %s is already used by another rack.') - % name) - if rack.subnet == subnet and other_record: - raise forms.ValidationError( - _('The subnet is already assigned to rack %s.') - % (rack.name)) - - return cleaned_data - - def __init__(self, request, *args, **kwargs): - super(RackCreateInfoAction, self).__init__(request, *args, **kwargs) - resource_class_id_choices = [('', _("Select a Resource Class"))] - for rc in tuskar.ResourceClass.list(request): - resource_class_id_choices.append((rc.id, rc.name)) - self.fields['resource_class_id'].choices = resource_class_id_choices - - class Meta: - name = _("Rack Settings") - - -class CreateRackInfo(workflows.Step): - action_class = RackCreateInfoAction - - contributes = ('name', 'resource_class_id', 'subnet', 'location') - - def get_racks_data(): - pass - - -class EditRackInfo(CreateRackInfo): - depends_on = ('rack_id',) - - -class NodeCreateAction(workflows.Action): - class Meta: - name = _("Create Nodes") - help_text = _("Here you can create the nodes for this rack.") - - def clean(self): - cleaned_data = super(NodeCreateAction, self).clean() - table = self.initial.get('_tables', {}).get('nodes') - if table: - formset = table.get_formset() - if formset.is_valid(): - cleaned_data['nodes'] = [ - form.cleaned_data for form in formset - if form.cleaned_data - and not form.cleaned_data.get('DELETE')] - else: - raise forms.ValidationError(_("Errors in the nodes list.")) - return cleaned_data - - -class NodeEditAction(NodeCreateAction): - class Meta: - name = _("Edit Nodes") - help_text = _("Here you can edit the nodes for this rack.") - - -class CreateNodes(tuskar_ui.workflows.TableStep): - action_class = NodeCreateAction - contributes = ('nodes',) - table_classes = (nodes_tables.NodesFormsetTable,) - template_name = ( - 'infrastructure/resource_management/racks/_rack_nodes_step.html') - - def get_nodes_data(self): - return [] - - -class EditNodes(CreateNodes): - action_class = NodeEditAction - depends_on = ('rack_id',) - - def get_nodes_data(self): - rack_id = self.workflow.context['rack_id'] - rack = tuskar.Rack.get(self.workflow.request, rack_id) - return rack.list_baremetal_nodes - - -class CreateRack(workflows.Workflow): - default_steps = (CreateRackInfo, CreateNodes) - slug = "create_rack" - name = _("Add Rack") - success_url = 'horizon:infrastructure:resource_management:index' - success_message = _("Rack created.") - failure_message = _("Unable to create rack.") - - # FIXME active tabs coflict - # When on page with tabs, the workflow with more steps is used, - # there is a conflict of active tabs and it always shows the - # first tab after an action. So I explicitly specify to what - # tab it should redirect after action, until the coflict will - # be fixed in Horizon. - def get_index_url(self): - """This URL is used both as success and failure URL.""" - return "%s?tab=resource_management_tabs__racks_tab" %\ - urlresolvers.reverse('horizon:infrastructure:resource_management:' - 'index') - - def get_success_url(self): - return self.get_index_url() - - def get_failure_url(self): - return self.get_index_url() - - def create_or_update_baremetal_node(self, baremetal_node_data): - """Creates (if id=='') or updates (otherwise) a baremetal node.""" - if baremetal_node_data['id'] not in ('', None): - baremetal_node_id = unicode(baremetal_node_data['id']) - # TODO(rdopieralski) there is currently no way to update - # a baremetal node - # - # tuskar.BaremetalNode.update( - # self.request, - # node_id=node_id, - # service_host=baremetal_node_data['service_host'], - # cpus=baremetal_node_data['cpus'], - # memory_mb=baremetal_node_data['memory_mb'], - # local_gb=baremetal_node_data['local_gb'], - # prov_mac_address=baremetal_node_data['mac_address'], - # pm_address=baremetal_node_data['pm_address'], - # pm_user=baremetal_node_data['pm_user'], - # pm_password=baremetal_node_data['pm_password'], - # terminal_port=baremetal_node_data['terminal_port']) - return baremetal_node_id - else: - baremetal_node = tuskar.BaremetalNode.create( - self.request, - service_host=baremetal_node_data['service_host'], - cpus=baremetal_node_data['cpus'], - memory_mb=baremetal_node_data['memory_mb'], - local_gb=baremetal_node_data['local_gb'], - prov_mac_address=baremetal_node_data['mac_address'], - pm_address=baremetal_node_data['pm_address'], - pm_user=baremetal_node_data['pm_user'], - pm_password=baremetal_node_data['pm_password'], - terminal_port=baremetal_node_data['terminal_port']) - return baremetal_node.id - - def handle(self, request, data): - # First, create and/or update nodes - baremetal_node_ids = [] - for baremetal_node_data in data['nodes']: - try: - baremetal_node_id = self.create_or_update_baremetal_node( - baremetal_node_data) - except Exception: - exceptions.handle(self.request, _("Unable to update node.")) - return False - else: - # Rack.create takes a list of dicts with BaremetalNode ids - baremetal_node_ids.append({'id': baremetal_node_id}) - try: - # Then, register the Rack, including the nodes - tuskar.Rack.create( - request, name=data['name'], - resource_class_id=data['resource_class_id'], - location=data['location'], subnet=data['subnet'], - baremetal_nodes=baremetal_node_ids) - - return True - except requests.ConnectionError: - messages.error(request, - _("Unable to connect to Nova Baremetal. Please " - "check your configuration.")) - return False - except Exception: - exceptions.handle(request, _("Unable to create rack.")) - return False - - -class EditRack(CreateRack): - default_steps = (EditRackInfo, EditNodes) - slug = "edit_rack" - name = _("Edit Rack") - success_url = 'horizon:infrastructure:resource_management:index' - success_message = _("Rack updated.") - failure_message = _("Unable to update rack.") - - def handle(self, request, data): - baremetal_nodes_data = data.pop('nodes') - baremetal_node_ids = [ - {'id': self.create_or_update_baremetal_node(baremetal_node_data)} - for baremetal_node_data in baremetal_nodes_data] - try: - rack_id = self.context['rack_id'] - data['baremetal_nodes'] = baremetal_node_ids - tuskar.Rack.update(request, rack_id, data) - return True - except Exception: - exceptions.handle(request, _("Unable to update rack.")) - return False - - -class DetailEditRack(EditRack): - success_url = 'horizon:infrastructure:resource_management:racks:detail' - - def get_success_url(self): - rack_id = self.context['rack_id'] - return urlresolvers.reverse(self.success_url, args=(rack_id,)) - - def get_failure_url(self): - rack_id = self.context['rack_id'] - return urlresolvers.reverse(self.success_url, args=(rack_id,)) diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/forms.py b/tuskar_ui/infrastructure/resource_management/resource_classes/forms.py deleted file mode 100644 index 7682c5bb..00000000 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/forms.py +++ /dev/null @@ -1,75 +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.core import urlresolvers -import django.forms -from django.utils.translation import ugettext_lazy as _ # noqa - -from horizon import exceptions -from horizon import forms -from horizon import messages - -from tuskar_ui import api as tuskar - -import logging - -LOG = logging.getLogger(__name__) - - -class DeleteForm(forms.SelfHandlingForm): - def __init__(self, request, *args, **kwargs): - super(DeleteForm, self).__init__(request, *args, **kwargs) - - resource_class = self.initial.get('resource_class', None) - self.command = DeleteCommand(request, resource_class) - - def handle(self, request, data): - try: - self.command.execute() - - messages.success(request, self.command.msg) - return True - except Exception: - exceptions.handle(request, _("Unable to delete Resource Class.")) - - -# TODO(this command will be reused in table, so code is not duplicated) -class DeleteCommand(object): - def __init__(self, request, resource_class): - self.resource_class = resource_class - self.request = request - self.header = (_("Deleting resource class '%s.'") - % self.resource_class.name) - self.msg = "" - - def execute(self): - try: - tuskar.ResourceClass.delete(self.request, - self.resource_class.id) - self.msg = (_('Successfully deleted Class "%s".') - % self.resource_class.name) - except Exception: - self.msg = _('Failed to delete Class %s') % self.resource_class.id - LOG.info(self.msg) - redirect = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index') - exceptions.handle(self.request, self.msg, redirect=redirect) - - -class SelectRack(django.forms.Form): - id = django.forms.IntegerField(widget=django.forms.HiddenInput()) - selected = django.forms.BooleanField(required=False) - - -SelectRackFormset = django.forms.formsets.formset_factory(SelectRack, extra=0) diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/tables.py b/tuskar_ui/infrastructure/resource_management/resource_classes/tables.py deleted file mode 100644 index d16b5abe..00000000 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/tables.py +++ /dev/null @@ -1,217 +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. - -import logging -import re - -from django.core import urlresolvers -from django.utils.translation import ugettext_lazy as _ # noqa - -from horizon import exceptions -from horizon import tables - -from tuskar_ui import api as tuskar -from tuskar_ui.infrastructure.resource_management.flavors\ - import forms as flavors_forms -from tuskar_ui.infrastructure.resource_management.racks\ - import tables as racks_tables -from tuskar_ui.infrastructure.resource_management import resource_classes -from tuskar_ui.infrastructure.resource_management.resource_classes\ - import forms -import tuskar_ui.tables - - -LOG = logging.getLogger(__name__) - - -class CreateResourceClass(tables.LinkAction): - name = "create_class" - verbose_name = _("Create Class") - url = "horizon:infrastructure:resource_management:resource_classes:create" - classes = ("ajax-modal", "btn-create") - - -class UpdateResourceClass(tables.LinkAction): - name = "edit_class" - verbose_name = _("Edit Class") - url = "horizon:infrastructure:resource_management:resource_classes:update" - classes = ("ajax-modal", "btn-edit") - - -class DeleteResourceClass(tables.DeleteAction): - data_type_singular = _("Resource Class") - data_type_plural = _("Resource Classes") - - def delete(self, request, obj_id): - try: - tuskar.ResourceClass.delete(request, obj_id) - except Exception: - msg = _('Failed to delete resource class %s') % obj_id - LOG.info(msg) - redirect = urlresolvers.reverse( - "horizon:infrastructure:resource_management:index") - exceptions.handle(request, msg, redirect=redirect) - - -class ResourcesClassFilterAction(tables.FilterAction): - def filter(self, table, instances, filter_string): - pass - - -class ResourceClassesTable(tables.DataTable): - name = tables.Column( - "name", link=("horizon:infrastructure:" - "resource_management:resource_classes:detail"), - verbose_name=_("Class Name")) - service_type = tables.Column("service_type", verbose_name=_("Class Type")) - racks_count = tables.Column("racks_count", verbose_name=_("Racks"), - empty_value="0") - nodes_count = tables.Column("nodes_count", verbose_name=_("Nodes"), - empty_value="0") - - class Meta: - name = "resource_classes" - verbose_name = ("Classes") - table_actions = (ResourcesClassFilterAction, CreateResourceClass, - DeleteResourceClass) - row_actions = (UpdateResourceClass, DeleteResourceClass) - - -class FlavorsFilterAction(tables.FilterAction): - def filter(self, table, instances, filter_string): - pass - - -class RacksFilterAction(tables.FilterAction): - def filter(self, table, instances, filter_string): - pass - - -class RacksTable(racks_tables.RacksTable): - class Meta: - name = "racks_table" - verbose_name = _("Racks") - table_actions = (RacksFilterAction,) - - -class RacksFormsetTable(tuskar_ui.tables.FormsetDataTableMixin, RacksTable): - formset_class = forms.SelectRackFormset - - class Meta: - name = "racks" - verbose_name = _("Racks") - multi_select = False - table_actions = (RacksFilterAction,) - - def __init__(self, *args, **kwargs): - # Adding a column at the left of the table. - selected = tables.Column('selected', verbose_name="", sortable=False) - selected.classes.append('narrow') - selected.table = self - self._columns.insert(0, 'selected', selected) - super(RacksFormsetTable, self).__init__(*args, **kwargs) - - -class UpdateRacksClass(tables.LinkAction): - name = "edit_flavors" - verbose_name = _("Edit Racks") - - classes = ("ajax-modal", "btn-edit") - - def get_link_url(self, datum=None): - url = ("horizon:infrastructure:resource_management:resource_classes:" - "update_racks") - return "%s?step=%s" % ( - urlresolvers.reverse( - url, - args=(self.table.kwargs['resource_class_id'],)), - resource_classes.workflows.RacksAction.slug) - - -class UpdateFlavorsClass(tables.LinkAction): - name = "edit_flavors" - verbose_name = _("Edit Flavors") - classes = ("ajax-modal", "btn-edit") - - def get_link_url(self, datum=None): - url = ("horizon:infrastructure:resource_management:resource_classes:" - "update_flavors") - resource_class_id = self.table.kwargs.get('resource_class_id') - return "%s?step=%s" % ( - urlresolvers.reverse(url, args=(resource_class_id,)), - resource_classes.workflows.ResourceClassFlavorsAction.slug) - - -class FlavorsTable(tables.DataTable): - def get_flavor_detail_link(datum): - # FIXME - horizon Column.get_link_url does not allow to access GET - # params - resource_class_id = re.findall("[0-9]+", datum.request.path)[-1] - return urlresolvers.reverse( - "horizon:infrastructure:resource_management:resource_classes:" - "flavors:detail", args=(resource_class_id, datum.id)) - - name = tables.Column( - 'name', - link=get_flavor_detail_link, - verbose_name=_('Flavor Name'), - ) - cpu = tables.Column( - "cpu", - verbose_name=_('VCPU'), - filters=(lambda x: getattr(x, 'value', ''),) - ) - memory = tables.Column( - "memory", - verbose_name=_('RAM (MB)'), - filters=(lambda x: getattr(x, 'value', ''),) - ) - storage = tables.Column( - "storage", - verbose_name=_('Root Disk (GB)'), - filters=(lambda x: getattr(x, 'value', ''),) - ) - ephemeral_disk = tables.Column( - "ephemeral_disk", - verbose_name=_('Ephemeral Disk (GB)'), - filters=(lambda x: getattr(x, 'value', ''),) - ) - swap_disk = tables.Column( - "swap_disk", - verbose_name=_('Swap Disk (MB)'), - filters=(lambda x: getattr(x, 'value', ''),) - ) - max_vms = tables.Column("max_vms", verbose_name=_("Max. VMs")) - - class Meta: - name = "flavors_table" - verbose_name = _("Flavors") - table_actions = (FlavorsFilterAction, UpdateFlavorsClass) - - -class FlavorsFormsetTable(tuskar_ui.tables.FormsetDataTableMixin, - FlavorsTable): - - name = tables.Column( - 'name', - verbose_name=_('Flavor Name'), - ) - DELETE = tables.Column('DELETE', verbose_name=_("Delete")) - formset_class = flavors_forms.FlavorFormset - - class Meta: - name = "flavors" - verbose_name = _("Flavors") - table_actions = () - multi_select = False diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/tabs.py b/tuskar_ui/infrastructure/resource_management/resource_classes/tabs.py deleted file mode 100644 index fcdbbf5a..00000000 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/tabs.py +++ /dev/null @@ -1,79 +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 _ # noqa - -from horizon import exceptions -from horizon import tabs - -from tuskar_ui.infrastructure.resource_management.resource_classes\ - import tables - - -class OverviewTab(tabs.Tab): - name = _("Overview") - slug = "overview" - template_name = ("infrastructure/resource_management/resource_classes/" - "_detail_overview.html") - # FIXME charts doesnt work if uncommented - #preload = False - - def get_context_data(self, request): - return {"resource_class": self.tab_group.kwargs['resource_class']} - - -class RacksTab(tabs.TableTab): - table_classes = (tables.RacksTable,) - name = _("Racks") - slug = "racks" - template_name = ("infrastructure/resource_management/resource_classes/" - "_detail_racks.html") - - def get_racks_table_data(self): - try: - resource_class = self.tab_group.kwargs['resource_class'] - racks = resource_class.list_racks - except Exception: - racks = [] - exceptions.handle(self.tab_group.request, - _('Unable to retrieve rack list.')) - return racks - - -class FlavorsTab(tabs.TableTab): - table_classes = (tables.FlavorsTable,) - name = _("Flavors") - slug = "flavors" - template_name = ("infrastructure/resource_management/resource_classes/" - "_detail_flavors.html") - - def get_flavors_table_data(self): - try: - resource_class = self.tab_group.kwargs['resource_class'] - flavors = resource_class.list_flavors - except Exception: - flavors = [] - exceptions.handle(self.tab_group.request, - _('Unable to retrieve flavor list.')) - return flavors - - def allowed(self, request): - resource_class = self.tab_group.kwargs['resource_class'] - return resource_class.service_type == "compute" - - -class ResourceClassDetailTabs(tabs.TabGroup): - slug = "resource_class_details" - tabs = (OverviewTab, RacksTab, FlavorsTab) - sticky = True diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/tests.py b/tuskar_ui/infrastructure/resource_management/resource_classes/tests.py deleted file mode 100644 index 94fac9ee..00000000 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/tests.py +++ /dev/null @@ -1,656 +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.core import urlresolvers -from django import http -from django.utils import simplejson - -import mox - -from openstack_dashboard.api import glance -from openstack_dashboard.test.test_data import glance_data - -from tuskar_ui import api as tuskar -from tuskar_ui.test import helpers as test - - -class ResourceClassViewTests(test.BaseAdminViewTests): - def setUp(self): - super(ResourceClassViewTests, self).setUp() - # Add the .images attribute for testing glance api call - glance_data.data(self) - - @test.create_stubs({ - tuskar.Rack: ('list',), - tuskar.ResourceClass: ('get',), - glance: ('image_list_detailed',), - }) - def test_create_resource_class_get(self): - all_racks = self.tuskar_racks.list() - rc = self.tuskar_resource_classes.first() - - glance.image_list_detailed(mox.IsA(http.HttpRequest)).AndReturn( - (self.images.list(), False)) - tuskar.Rack.list( - mox.IsA(http.HttpRequest), True).AndReturn(all_racks) - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), rc.id).AndReturn(rc) - self.mox.ReplayAll() - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:resource_classes:' - 'create') - res = self.client.get(url) - self.assertEqual(res.status_code, 200) - - @test.create_stubs({ - tuskar.ResourceClass: ('list', 'create', 'set_racks'), - tuskar.Rack: ('list',), - glance: ('image_list_detailed',), - }) - def test_create_resource_class_post(self): - new_resource_class = self.tuskar_resource_classes.first() - new_unique_name = "unique_name_for_sure" - new_flavors = [] - image_id = self.images.list()[0].id - - add_racks_ids = [] - - glance.image_list_detailed(mox.IsA(http.HttpRequest)).AndReturn( - (self.images.list(), False)) - tuskar.Rack.list( - mox.IsA(http.HttpRequest), True).AndReturn([]) - tuskar.ResourceClass.list( - mox.IsA(http.HttpRequest)).AndReturn( - self.tuskar_resource_classes.list()) - tuskar.ResourceClass.create( - mox.IsA(http.HttpRequest), - name=new_unique_name, - service_type=new_resource_class.service_type, - image_id=image_id, - flavors=new_flavors).AndReturn(new_resource_class) - tuskar.ResourceClass.set_racks(mox.IsA(http.HttpRequest), - add_racks_ids) - self.mox.ReplayAll() - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:resource_classes:' - 'create') - form_data = { - 'name': new_unique_name, - 'service_type': new_resource_class.service_type, - 'image_id': image_id, - 'flavors-TOTAL_FORMS': 0, - 'flavors-INITIAL_FORMS': 0, - 'flavors-MAX_NUM_FORMS': 1000, - 'racks-TOTAL_FORMS': 0, - 'racks-INITIAL_FORMS': 0, - 'racks-MAX_NUM_FORMS': 1000, - } - res = self.client.post(url, form_data) - self.assertNoFormErrors(res) - self.assertMessageCount(success=1) - - redirect_url = ( - "%s?tab=resource_management_tabs__resource_classes_tab" % - urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:index')) - self.assertRedirectsNoFollow(res, redirect_url) - - @test.create_stubs({ - tuskar.ResourceClass: ('list', 'create', 'set_racks'), - tuskar.Rack: ('list',), - glance: ('image_list_detailed',), - }) - def test_create_resource_class_post_exception(self): - new_resource_class = self.tuskar_resource_classes.first() - new_unique_name = "unique_name_for_sure" - new_flavors = [] - image_id = self.images.list()[0].id - - glance.image_list_detailed(mox.IsA(http.HttpRequest)).AndReturn( - (self.images.list(), False)) - tuskar.Rack.list( - mox.IsA(http.HttpRequest), True).AndReturn([]) - tuskar.ResourceClass.list( - mox.IsA(http.HttpRequest)).AndReturn( - self.tuskar_resource_classes.list()) - tuskar.ResourceClass.\ - create(mox.IsA(http.HttpRequest), name=new_unique_name, - service_type=new_resource_class.service_type, - image_id=image_id, - flavors=new_flavors).\ - AndRaise(self.exceptions.tuskar) - self.mox.ReplayAll() - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:' - 'resource_classes:create') - form_data = { - 'name': new_unique_name, - 'service_type': new_resource_class.service_type, - 'image_id': image_id, - 'flavors-TOTAL_FORMS': 0, - 'flavors-INITIAL_FORMS': 0, - 'flavors-MAX_NUM_FORMS': 1000, - 'racks-TOTAL_FORMS': 0, - 'racks-INITIAL_FORMS': 0, - 'racks-MAX_NUM_FORMS': 1000, - } - res = self.client.post(url, form_data) - self.assertRedirectsNoFollow( - res, - ("%s?tab=resource_management_tabs__resource_classes_tab" % - urlresolvers. - reverse("horizon:infrastructure:resource_management:index"))) - - @test.create_stubs({ - tuskar.ResourceClass: ('get', 'list_flavors', 'racks_ids', - 'all_racks'), - glance: ('image_list_detailed',), - }) - def test_edit_resource_class_get(self): - resource_class = self.tuskar_resource_classes.first() - all_flavors = [] - all_racks = [] - - glance.image_list_detailed(mox.IsA(http.HttpRequest)).AndReturn( - (self.images.list(), False)) - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), - resource_class.id).AndReturn(resource_class) - - # get_flavors_data in workflows.py - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), - resource_class.id).AndReturn(resource_class) - - # get_racks_data in workflows.py - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), - resource_class.id).AndReturn(resource_class) - - self.mox.ReplayAll() - - # FIXME I should probably track the racks and flavors methods - # so maybe they shouldn't be a @property - # properties set - tuskar.ResourceClass.all_racks = all_racks - tuskar.ResourceClass.list_flavors = all_flavors - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:resource_classes:' - 'update', - args=[resource_class.id]) - res = self.client.get(url) - self.assertEqual(res.status_code, 200) - - @test.create_stubs({ - tuskar.ResourceClass: ('get', 'list_flavors', - 'racks_ids', 'all_racks'), - glance: ('image_list_detailed',), - }) - def test_edit_resource_class_get_exception(self): - resource_class = self.tuskar_resource_classes.first() - - tuskar.ResourceClass.\ - get(mox.IsA(http.HttpRequest), resource_class.id)\ - .AndRaise(self.exceptions.tuskar) - - self.mox.ReplayAll() - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:' - 'resource_classes:update', - args=[resource_class.id]) - res = self.client.get(url) - self.assertRedirectsNoFollow( - res, urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index')) - - @test.create_stubs({ - tuskar.ResourceClass: ('get', 'list', 'update', 'set_racks', - 'list_flavors', 'all_racks', 'racks_ids'), - tuskar.Rack: ('list',), - glance: ('image_list_detailed',), - }) - def test_edit_resource_class_post(self): - resource_class = self.tuskar_resource_classes.first() - image_id = self.images.list()[0].id - - add_racks_ids = [] - - glance.image_list_detailed(mox.IsA(http.HttpRequest)).AndReturn( - (self.images.list(), False)) - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), resource_class.id).AndReturn( - resource_class) - tuskar.ResourceClass.all_racks = [] - tuskar.ResourceClass.racks_ids = [] - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), resource_class.id).AndReturn( - resource_class) - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), resource_class.id).AndReturn( - resource_class) - tuskar.ResourceClass.list_flavors = [] - tuskar.ResourceClass.list( - mox.IsA(http.HttpRequest)).AndReturn( - self.tuskar_resource_classes.list()) - tuskar.ResourceClass.update(mox.IsA(http.HttpRequest), - resource_class.id, - name=resource_class.name, - service_type=resource_class.service_type, - image_id=image_id, - flavors=[]).AndReturn(resource_class) - tuskar.ResourceClass.set_racks(mox.IsA(http.HttpRequest), - add_racks_ids) - self.mox.ReplayAll() - - form_data = { - 'resource_class_id': resource_class.id, - 'name': resource_class.name, - 'service_type': resource_class.service_type, - 'image_id': image_id, - 'flavors-TOTAL_FORMS': 0, - 'flavors-INITIAL_FORMS': 0, - 'flavors-MAX_NUM_FORMS': 1000, - 'racks-TOTAL_FORMS': 0, - 'racks-INITIAL_FORMS': 0, - 'racks-MAX_NUM_FORMS': 1000, - } - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:resource_classes:' - 'update', - args=[resource_class.id]) - res = self.client.post(url, form_data) - self.assertNoFormErrors(res) - self.assertMessageCount(success=1) - - redirect_url = ( - "%s?tab=resource_management_tabs__resource_classes_tab" % - urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:index')) - self.assertRedirectsNoFollow(res, redirect_url) - - @test.create_stubs({tuskar.ResourceClass: ('delete', 'list')}) - def test_delete_resource_class(self): - resource_class = self.tuskar_resource_classes.first() - all_resource_classes = self.tuskar_resource_classes.list() - - tuskar.ResourceClass.delete(mox.IsA(http.HttpRequest), - resource_class.id) - tuskar.ResourceClass.list( - mox.IsA(http.HttpRequest)).AndReturn(all_resource_classes) - self.mox.ReplayAll() - - form_data = {'action': - 'resource_classes__delete__%s' % resource_class.id} - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index') - res = self.client.post(url, form_data) - - redirect_url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index') - self.assertRedirectsNoFollow(res, redirect_url) - - @test.create_stubs({tuskar.ResourceClass: ('delete', 'list')}) - def test_delete_resource_class_exception(self): - resource_class = self.tuskar_resource_classes.first() - all_resource_classes = self.tuskar_resource_classes.list() - - tuskar.ResourceClass.delete( - mox.IsA(http.HttpRequest), - resource_class.id).AndRaise(self.exceptions.tuskar) - tuskar.ResourceClass.list( - mox.IsA(http.HttpRequest)).\ - AndReturn(all_resource_classes) - self.mox.ReplayAll() - - form_data = {'action': - 'resource_classes__delete__%s' % resource_class.id} - res = self.client.post( - urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index'), - form_data) - # FIXME: there should be a better test than this, but the message - # is unreadable in a redirect response - self.assertRedirectsNoFollow( - res, urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index')) - - @test.create_stubs({ - tuskar.ResourceClass: ('get', 'list_flavors', 'list_racks', - 'tuskar_nodes') - }) - def test_detail_get(self): - resource_class = self.tuskar_resource_classes.first() - flavors = [] - racks = [] - - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), resource_class.id).\ - AndReturn(resource_class) - self.mox.ReplayAll() - - tuskar.ResourceClass.list_flavors = flavors - tuskar.ResourceClass.list_racks = racks - tuskar.ResourceClass.tuskar_nodes = [] - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:resource_classes:' - 'detail', - args=[resource_class.id]) - res = self.client.get(url) - self.assertItemsEqual(res.context['flavors_table_table'].data, flavors) - self.assertItemsEqual(res.context['racks_table_table'].data, racks) - self.assertEqual(res.status_code, 200) - self.assertTemplateUsed( - res, - 'infrastructure/resource_management/resource_classes/detail.html') - - @test.create_stubs({ - tuskar.ResourceClass: ('get',) - }) - def test_detail_action_get(self): - resource_class = self.tuskar_resource_classes.first() - - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), - resource_class.id).AndReturn(resource_class) - - self.mox.ReplayAll() - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:resource_classes:' - 'detail_action', args=[resource_class.id]) + "?action=delete" - res = self.client.get(url) - self.assertEqual(res.status_code, 200) - - @test.create_stubs({ - tuskar.ResourceClass: ('get', 'delete') - }) - def test_detail_action_post(self): - resource_class = self.tuskar_resource_classes.first() - - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), - resource_class.id).AndReturn(resource_class) - tuskar.ResourceClass.delete(mox.IsA(http.HttpRequest), - resource_class.id) - - self.mox.ReplayAll() - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:resource_classes:' - 'detail_action', args=[resource_class.id]) + "?action=delete" - res = self.client.post(url) - self.assertNoFormErrors(res) - self.assertMessageCount(success=1) - - redirect_url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:index') - self.assertRedirectsNoFollow(res, redirect_url) - - @test.create_stubs({ - tuskar.ResourceClass: ('get', 'list_racks') - }) - def test_rack_health_get(self): - resource_class = self.tuskar_resource_classes.first() - racks = [self.tuskar_racks.first()] - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), - resource_class.id).\ - AndReturn(resource_class) - self.mox.ReplayAll() - - tuskar.ResourceClass.list_racks = racks - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:' - 'resource_classes:rack_health', args=[resource_class.id]) - res = self.client.get(url) - data = simplejson.loads(res.content)['data'] - - # FIXME: this is dummy data right now, just assert its presence - self.assertEqual(len(data), 1) - self.assertEqual(data[0]['name'], 'rack1') - - @test.create_stubs({ - tuskar.ResourceClass: ('get', 'list_flavors', 'list_racks') - }) - def test_detail_get_exception(self): - resource_class = self.tuskar_resource_classes.first() - - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), - resource_class.id).\ - AndRaise(self.exceptions.tuskar) - self.mox.ReplayAll() - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:' - 'resource_classes:detail', args=[resource_class.id]) - res = self.client.get(url) - self.assertRedirectsNoFollow( - res, urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index')) - - @test.create_stubs({ - tuskar.ResourceClass: ('get', 'list_flavors', - 'racks_ids', 'all_racks'), - glance: ('image_list_detailed',), - }) - def test_detail_edit_racks_get(self): - resource_class = self.tuskar_resource_classes.first() - all_flavors = [] - all_racks = [] - - glance.image_list_detailed(mox.IsA(http.HttpRequest)).AndReturn( - (self.images.list(), False)) - tuskar.ResourceClass.get(mox.IsA(http.HttpRequest), - resource_class.id).AndReturn(resource_class) - - # get_flavors_data in workflows.py - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), - resource_class.id).AndReturn(resource_class) - - # get_racks_data in workflows.py - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), - resource_class.id).AndReturn(resource_class) - - self.mox.ReplayAll() - - # FIXME I should probably track the racks and flavors methods - # so maybe they shouldn't be a @property - # properties set - tuskar.ResourceClass.all_racks = all_racks - tuskar.ResourceClass.list_flavors = all_flavors - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:resource_classes:' - 'update_racks', - args=[resource_class.id]) - res = self.client.get(url) - self.assertEqual(res.status_code, 200) - - @test.create_stubs({ - tuskar.ResourceClass: ('get', 'list', 'update', 'set_racks', - 'list_flavors', 'all_racks', 'racks_ids'), - glance: ('image_list_detailed',), - }) - def test_detail_edit_racks_post(self): - resource_class = self.tuskar_resource_classes.first() - image_id = self.images.list()[0].id - add_racks_ids = [] - - glance.image_list_detailed(mox.IsA(http.HttpRequest)).AndReturn( - (self.images.list(), False)) - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), resource_class.id).AndReturn( - resource_class) - tuskar.ResourceClass.all_racks = [] - tuskar.ResourceClass.racks_ids = [] - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), resource_class.id).AndReturn( - resource_class) - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), resource_class.id).AndReturn( - resource_class) - tuskar.ResourceClass.list_flavors = [] - tuskar.ResourceClass.list( - mox.IsA(http.HttpRequest)).AndReturn( - self.tuskar_resource_classes.list()) - tuskar.ResourceClass.update(mox.IsA(http.HttpRequest), - resource_class.id, - name=resource_class.name, - service_type=resource_class.service_type, - image_id=image_id, - flavors=[]).AndReturn(resource_class) - tuskar.ResourceClass.set_racks(mox.IsA(http.HttpRequest), - add_racks_ids) - self.mox.ReplayAll() - - form_data = { - 'resource_class_id': resource_class.id, - 'name': resource_class.name, - 'service_type': resource_class.service_type, - 'image_id': image_id, - 'flavors-TOTAL_FORMS': 0, - 'flavors-INITIAL_FORMS': 0, - 'flavors-MAX_NUM_FORMS': 1000, - 'racks-TOTAL_FORMS': 0, - 'racks-INITIAL_FORMS': 0, - 'racks-MAX_NUM_FORMS': 1000, - } - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:resource_classes:' - 'update_racks', - args=[resource_class.id]) - res = self.client.post(url, form_data) - self.assertNoFormErrors(res) - self.assertMessageCount(success=1) - - detail_url = ('horizon:infrastructure:resource_management:' - 'resource_classes:detail') - redirect_url = ( - "%s?tab=resource_class_details__racks" % - urlresolvers.reverse(detail_url, args=(resource_class.id,))) - self.assertRedirectsNoFollow(res, redirect_url) - - @test.create_stubs({ - tuskar.ResourceClass: ('get', 'list_flavors', - 'racks_ids', 'all_racks'), - glance: ('image_list_detailed',), - }) - def test_detail_edit_flavors_get(self): - resource_class = self.tuskar_resource_classes.first() - all_flavors = [] - all_racks = [] - - glance.image_list_detailed(mox.IsA(http.HttpRequest)).AndReturn( - (self.images.list(), False)) - tuskar.ResourceClass.get(mox.IsA(http.HttpRequest), - resource_class.id).AndReturn(resource_class) - - # get_flavors_data in workflows.py - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), - resource_class.id).AndReturn(resource_class) - - # get_racks_data in workflows.py - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), - resource_class.id).AndReturn(resource_class) - - self.mox.ReplayAll() - - # FIXME I should probably track the racks and flavors methods - # so maybe they shouldn't be a @property - # properties set - tuskar.ResourceClass.all_racks = all_racks - tuskar.ResourceClass.list_flavors = all_flavors - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:resource_classes:' - 'update_flavors', - args=[resource_class.id]) - res = self.client.get(url) - self.assertEqual(res.status_code, 200) - - @test.create_stubs({ - tuskar.ResourceClass: ('get', 'list', 'update', 'set_racks', - 'list_flavors', 'all_racks', 'racks_ids'), - tuskar.Rack: ('list',), - glance: ('image_list_detailed',), - }) - def test_detail_edit_flavors_post(self): - resource_class = self.tuskar_resource_classes.first() - image_id = self.images.list()[0].id - add_racks_ids = [] - - glance.image_list_detailed(mox.IsA(http.HttpRequest)).AndReturn( - (self.images.list(), False)) - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), resource_class.id).AndReturn( - resource_class) - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), resource_class.id).AndReturn( - resource_class) - tuskar.ResourceClass.all_racks = [] - tuskar.ResourceClass.racks_ids = [] - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), resource_class.id).AndReturn( - resource_class) - tuskar.ResourceClass.list_flavors = [] - tuskar.ResourceClass.list( - mox.IsA(http.HttpRequest)).AndReturn( - self.tuskar_resource_classes.list()) - tuskar.ResourceClass.update(mox.IsA(http.HttpRequest), - resource_class.id, - name=resource_class.name, - service_type=resource_class.service_type, - image_id=image_id, - flavors=[]).AndReturn(resource_class) - tuskar.ResourceClass.set_racks(mox.IsA(http.HttpRequest), - add_racks_ids) - self.mox.ReplayAll() - - form_data = { - 'resource_class_id': resource_class.id, - 'name': resource_class.name, - 'service_type': resource_class.service_type, - 'image_id': image_id, - 'flavors-TOTAL_FORMS': 0, - 'flavors-INITIAL_FORMS': 0, - 'flavors-MAX_NUM_FORMS': 1000, - 'racks-TOTAL_FORMS': 0, - 'racks-INITIAL_FORMS': 0, - 'racks-MAX_NUM_FORMS': 1000, - } - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:resource_classes:' - 'update_flavors', - args=[resource_class.id]) - res = self.client.post(url, form_data) - self.assertNoFormErrors(res) - self.assertMessageCount(success=1) - - redirect_url = ('horizon:infrastructure:resource_management:' - 'resource_classes:detail') - redirect_url = "%s?tab=resource_class_details__flavors" % ( - urlresolvers.reverse(redirect_url, args=(resource_class.id,))) - self.assertRedirectsNoFollow(res, redirect_url) diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/urls.py b/tuskar_ui/infrastructure/resource_management/resource_classes/urls.py deleted file mode 100644 index dbc4ab1c..00000000 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/urls.py +++ /dev/null @@ -1,52 +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.resource_management.flavors\ - import urls as flavor_urls -from tuskar_ui.infrastructure.resource_management.resource_classes import views - - -RESOURCE_CLASS = r'^(?P<resource_class_id>[^/]+)/%s$' -VIEW_MOD = ('tuskar_ui.infrastructure.resource_management.resource_classes.' - 'views') - -urlpatterns = defaults.patterns( - VIEW_MOD, - defaults.url(r'^create/$', views.CreateView.as_view(), name='create'), - defaults.url(r'^(?P<resource_class_id>[^/]+)/$', - views.DetailView.as_view(), - name='detail'), - defaults.url(RESOURCE_CLASS % 'update', - views.UpdateView.as_view(), - name='update'), - defaults.url(RESOURCE_CLASS % 'detail_action', - views.DetailActionView.as_view(), - name='detail_action'), - defaults.url(RESOURCE_CLASS % 'detail_update', - views.DetailUpdateView.as_view(), - name='detail_update'), - defaults.url(RESOURCE_CLASS % 'update_racks', - views.UpdateRacksView.as_view(), - name='update_racks'), - defaults.url(RESOURCE_CLASS % 'update_flavors', - views.UpdateFlavorsView.as_view(), - name='update_flavors'), - defaults.url(RESOURCE_CLASS % 'rack_health.json', - 'rack_health', - name='rack_health'), - defaults.url(r'^(?P<resource_class_id>[^/]+)/flavors/', - defaults.include(flavor_urls, namespace='flavors')), -) diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/views.py b/tuskar_ui/infrastructure/resource_management/resource_classes/views.py deleted file mode 100644 index 786f2579..00000000 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/views.py +++ /dev/null @@ -1,196 +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. - -""" -Views for managing resource classes -""" -import logging -import random - -from django.core import urlresolvers -import django.http -from django.utils import simplejson -from django.utils.translation import ugettext_lazy as _ # noqa - -from horizon import exceptions -from horizon import forms as horizon_forms -from horizon import tabs as horizon_tabs - -from tuskar_ui import api as tuskar - -from tuskar_ui.infrastructure.resource_management.resource_classes import forms -from tuskar_ui.infrastructure.resource_management.resource_classes import tabs -from tuskar_ui.infrastructure.resource_management.resource_classes\ - import workflows -from tuskar_ui import workflows as tuskar_workflows - - -LOG = logging.getLogger(__name__) - - -class CreateView(tuskar_workflows.WorkflowView): - workflow_class = workflows.CreateResourceClass - - def get_initial(self): - pass - - -class UpdateView(tuskar_workflows.WorkflowView): - workflow_class = workflows.UpdateResourceClass - - def get_context_data(self, **kwargs): - context = super(UpdateView, self).get_context_data(**kwargs) - context["resource_class_id"] = self.kwargs['resource_class_id'] - return context - - def _get_object(self, *args, **kwargs): - if not hasattr(self, "_object"): - resource_class_id = self.kwargs['resource_class_id'] - try: - self._object = \ - tuskar.ResourceClass.get(self.request, - resource_class_id) - except Exception: - redirect = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:index') - msg = _('Unable to retrieve resource class details.') - exceptions.handle(self.request, msg, redirect=redirect) - - return self._object - - def get_initial(self): - resource_class = self._get_object() - - return { - 'resource_class_id': resource_class.id, - 'name': resource_class.name, - 'service_type': resource_class.service_type, - 'image_id': resource_class.image_id, - } - - -class DetailUpdateView(UpdateView): - workflow_class = workflows.DetailUpdateWorkflow - - -class UpdateRacksView(UpdateView): - workflow_class = workflows.UpdateRacksWorkflow - - -class UpdateFlavorsView(UpdateView): - workflow_class = workflows.UpdateFlavorsWorkflow - - -class DetailView(horizon_tabs.TabView): - tab_group_class = tabs.ResourceClassDetailTabs - template_name = ('infrastructure/resource_management/resource_classes/' - 'detail.html') - - def get_context_data(self, **kwargs): - context = super(DetailView, self).get_context_data(**kwargs) - context["resource_class"] = self.get_data() - return context - - def get_data(self): - if not hasattr(self, "_resource_class"): - try: - resource_class_id = self.kwargs['resource_class_id'] - resource_class = tuskar.ResourceClass.get(self.request, - resource_class_id) - except Exception: - redirect = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:index') - exceptions.handle(self.request, - _('Unable to retrieve details for ' - 'resource class "%s".') - % resource_class_id, redirect=redirect) - self._resource_class = resource_class - return self._resource_class - - def get_tabs(self, request, *args, **kwargs): - resource_class = self.get_data() - return self.tab_group_class(request, resource_class=resource_class, - **kwargs) - - -class DetailActionView(horizon_forms.ModalFormView): - template_name = ('infrastructure/resource_management/' - 'resource_classes/action.html') - - def get_form(self, form_class): - """Returns an instance of the form to be used in this view.""" - try: - action = self.request.GET.get('action') - if action == "delete": - form_class = forms.DeleteForm - - return form_class(self.request, **self.get_form_kwargs()) - except Exception: - exceptions.handle(self.request, _("Unable to build an Action.")) - - def get_success_url(self): - # FIXME this should be set on form level - return urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:index') - - def get_context_data(self, **kwargs): - context = super(DetailActionView, self).get_context_data(**kwargs) - context['resource_class_id'] = self.kwargs['resource_class_id'] - context['action'] = context['form'].initial.get('action', None) - context['header'] = context['form'].command.header - return context - - def get_initial(self): - try: - resource_class = tuskar.ResourceClass.get( - self.request, self.kwargs['resource_class_id']) - action = self.request.GET.get('action') - except Exception: - exceptions.handle(self.request, - _("Unable to retrieve resource class data.")) - return {'resource_class': resource_class, - 'action': action} - - -def rack_health(request, resource_class_id=None): - # FIXME replace mock data - random.seed() - data = [] - statuses = ["Good", "Warnings", "Disaster"] - colors = ["rgb(244,244,244)", "rgb(240,170,0)", "rgb(200,0,0)"] - - resource_class = (tuskar.ResourceClass.get(request, - resource_class_id)) - for rack in resource_class.list_racks: - rand_index = random.randint(0, 2) - percentage = (2 - rand_index) * 50 - color = colors[rand_index] - - tooltip = ("<p>Rack: <strong>{0}</strong></p><p>{1}</p>").format( - rack.name, - statuses[rand_index]) - - data.append({'tooltip': tooltip, - 'color': color, - 'status': statuses[rand_index], - 'percentage': percentage, - 'id': rack.id, - 'name': rack.name, - 'url': "FIXME url"}) - - data.sort(key=lambda x: x['percentage']) - - res = {'data': data} - return django.http.HttpResponse(simplejson.dumps(res), - mimetype="application/json") diff --git a/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py b/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py deleted file mode 100644 index 08227106..00000000 --- a/tuskar_ui/infrastructure/resource_management/resource_classes/workflows.py +++ /dev/null @@ -1,350 +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.core import urlresolvers -from django.utils.translation import ugettext_lazy as _ # noqa - -from horizon import exceptions -from horizon import forms -from horizon import workflows -from openstack_dashboard.api import glance - -from tuskar_ui import api as tuskar -from tuskar_ui.infrastructure.resource_management.flavors\ - import forms as flavors_forms -from tuskar_ui.infrastructure.resource_management.resource_classes\ - import tables -import tuskar_ui.workflows - - -TEMPLATE_PREFIX = 'infrastructure/resource_management/resource_classes/' -URL_PREFIX = 'horizon:infrastructure:resource_management:' - - -class ResourceClassInfoAction(workflows.Action): - name = forms.CharField(max_length=255, - label=_("Class Name"), - help_text="", - required=True) - service_type = forms.ChoiceField(label=_('Class Type'), - required=True, - choices=[('', ''), - ('controller', - ('Controller')), - ('compute', - ('Compute')), - ('object_storage', - ('Object Storage')), - ('block_storage', - ('Block Storage')), - ], - widget=forms.Select( - attrs={'class': 'switchable'}) - ) - image_id = forms.ChoiceField( - label=_('Provisioning Image'), - required=True, - choices=[], - widget=forms.Select(attrs={'class': 'switchable'}), - ) - - def __init__(self, *args, **kwargs): - super(ResourceClassInfoAction, self).__init__(*args, **kwargs) - try: - images, more = glance.image_list_detailed(self.request) - except Exception: - exceptions.handle(self.request, - _('Unable to retrieve image list.')) - else: - self.fields['image_id'].choices = [ - (image.id, image.name) for image in images] - - def clean(self): - cleaned_data = super(ResourceClassInfoAction, self).clean() - - name = cleaned_data.get('name') - resource_class_id = self.initial.get('resource_class_id', None) - try: - resource_classes = tuskar.ResourceClass.list(self.request) - except Exception: - resource_classes = [] - msg = _('Unable to get resource class list') - exceptions.check_message(["Connection", "refused"], msg) - raise - for resource_class in resource_classes: - if resource_class.name == name and \ - resource_class_id != resource_class.id: - raise forms.ValidationError( - _('The name "%s" is already used by' - ' another resource class.') - % name - ) - return cleaned_data - - class Meta: - name = _("Class Settings") - help_text = _("From here you can fill in the class settings.") - - -class CreateResourceClassInfo(workflows.Step): - action_class = ResourceClassInfoAction - contributes = ("name", "service_type", "image_id") - - -class ResourceClassFlavorsAction(workflows.Action): - def clean(self): - cleaned_data = super(ResourceClassFlavorsAction, self).clean() - table = self.initial.get('_tables', {}).get('flavors') - if table: - formset = table.get_formset() - if formset.is_valid(): - cleaned_data['flavors'] = [form.cleaned_data - for form in formset - if form.cleaned_data - and not form.cleaned_data['DELETE']] - else: - raise forms.ValidationError(_('Errors in the flavors list.')) - return cleaned_data - - class Meta: - name = _("Flavors") - help_text = _("From here you can add flavors to the class.") - - -class CreateResourceClassFlavors(tuskar_ui.workflows.TableStep): - table_classes = (tables.FlavorsFormsetTable,) - - action_class = ResourceClassFlavorsAction - template_name = TEMPLATE_PREFIX + '_flavors_step.html' - contributes = ("flavors",) - - def get_flavors_data(self): - try: - resource_class_id = self.workflow.context.get("resource_class_id") - if resource_class_id: - resource_class = tuskar.ResourceClass.get( - self.workflow.request, resource_class_id) - flavors = resource_class.list_flavors - else: - flavors = [] - except Exception: - flavors = [] - exceptions.handle(self.workflow.request, - _('Unable to retrieve resource flavors list.')) - return flavors - - -class RacksAction(workflows.Action): - class Meta: - name = _("Racks") - - def clean(self): - cleaned_data = super(RacksAction, self).clean() - table = self.initial.get('_tables', {}).get('racks') - if table: - formset = table.get_formset() - if formset.is_valid(): - cleaned_data['racks_object_ids'] = [ - form.cleaned_data['id'] for form in formset - if form.cleaned_data and - form.cleaned_data.get('selected') and - not form.cleaned_data.get('DELETE')] - else: - raise forms.ValidationError(_('Errors in the racks table.')) - return cleaned_data - - -class CreateRacks(tuskar_ui.workflows.TableStep): - table_classes = (tables.RacksFormsetTable,) - - action_class = RacksAction - contributes = ("racks_object_ids") - template_name = TEMPLATE_PREFIX + '_table_step.html' - - def contribute(self, data, context): - context.update(data) - return context - - def get_racks_data(self): - try: - resource_class_id = self.workflow.context.get("resource_class_id") - if resource_class_id: - resource_class = tuskar.ResourceClass.get( - self.workflow.request, - resource_class_id) - selected_racks = resource_class.racks_ids - racks = resource_class.all_racks - for rack in racks: - rack.selected = (rack.id in selected_racks) - else: - racks = tuskar.Rack.list(self.workflow.request, True) - except Exception: - racks = [] - exceptions.handle(self.workflow.request, - _('Unable to retrieve racks list.')) - - return racks - - -class ResourceClassWorkflowMixin: - # FIXME active tabs coflict - # When on page with tabs, the workflow with more steps is used, - # there is a conflict of active tabs and it always shows the - # first tab after an action. So I explicitly specify to what - # tab it should redirect after action, until the coflict will - # be fixed in Horizon. - def get_index_url(self): - # This url is used both as success and failure url - return "%s?tab=resource_management_tabs__resource_classes_tab" % ( - urlresolvers.reverse(URL_PREFIX + 'index')) - - def get_success_url(self): - return self.get_index_url() - - def get_failure_url(self): - return self.get_index_url() - - def format_status_message(self, message): - name = self.context.get('name') - return message % name - - def _get_flavors(self, request, data): - flavors = [] - for flavor in data.get('flavors') or []: - capacities = [] - for name, info in flavors_forms.CAPACITIES.items(): - label, unit, required = info - value = flavor.get(name, '') - if value is None: - value = '' - capacities.append({'name': name, 'value': str(value), - 'unit': unit}) - # FIXME: for now just use blank max_vms - flavors.append({'name': flavor['name'], 'capacities': capacities, - 'max_vms': None, 'id': data.get('id')}) - return flavors - - def _add_racks(self, request, data, resource_class): - ids_to_add = data.get('racks_object_ids') or [] - resource_class.set_racks(request, ids_to_add) - - -class CreateResourceClass(ResourceClassWorkflowMixin, workflows.Workflow): - default_steps = (CreateResourceClassInfo, CreateResourceClassFlavors, - CreateRacks) - - slug = "create_resource_class" - name = _("Create Class") - finalize_button_name = _("Create Class") - success_message = _('Created class "%s".') - failure_message = _('Unable to create class "%s".') - - def _create_resource_class_info(self, request, data): - try: - if data['service_type'] == 'compute': - flavors = self._get_flavors(request, data) - else: - flavors = [] - return tuskar.ResourceClass.create( - request, - name=data['name'], - service_type=data['service_type'], - image_id=data['image_id'], - flavors=flavors) - except Exception: - redirect = self.get_failure_url() - exceptions.handle(request, - _('Unable to create resource class.'), - redirect=redirect) - return None - - def handle(self, request, data): - resource_class = self._create_resource_class_info(request, data) - self._add_racks(request, data, resource_class) - return True - - -class UpdateResourceClassInfo(CreateResourceClassInfo): - depends_on = ("resource_class_id",) - - -class UpdateResourceClassFlavors(CreateResourceClassFlavors): - depends_on = ("resource_class_id",) - - -class UpdateRacks(CreateRacks): - depends_on = ("resource_class_id",) - - -class UpdateResourceClass(ResourceClassWorkflowMixin, workflows.Workflow): - default_steps = (UpdateResourceClassInfo, UpdateResourceClassFlavors, - UpdateRacks) - - slug = "update_resource_class" - name = _("Update Class") - finalize_button_name = _("Update Class") - success_message = _('Updated class "%s".') - failure_message = _('Unable to update class "%s".') - - def _update_resource_class_info(self, request, data): - try: - if data['service_type'] == 'compute': - flavors = self._get_flavors(request, data) - else: - flavors = [] - return tuskar.ResourceClass.update( - request, - data['resource_class_id'], - name=data['name'], - service_type=data['service_type'], - image_id=data['image_id'], - flavors=flavors) - except Exception: - redirect = self.get_failure_url() - exceptions.handle(request, - _('Unable to create resource class.'), - redirect=redirect) - return None - - def handle(self, request, data): - resource_class = self._update_resource_class_info(request, data) - self._add_racks(request, data, resource_class) - return True - - -class DetailUpdateWorkflow(UpdateResourceClass): - def get_index_url(self): - # This url is used both as success and failure url - url = URL_PREFIX + "resource_classes:detail" - resource_class_id = self.context["resource_class_id"] - return "%s?tab=resource_class_details__overview" % ( - urlresolvers.reverse(url, args=(resource_class_id,))) - - -class UpdateFlavorsWorkflow(UpdateResourceClass): - def get_index_url(self): - # This url is used both as success and failure url - url = URL_PREFIX + "resource_classes:detail" - resource_class_id = self.context["resource_class_id"] - return "%s?tab=resource_class_details__flavors" % ( - urlresolvers.reverse(url, args=(resource_class_id,))) - - -class UpdateRacksWorkflow(UpdateResourceClass): - def get_index_url(self): - # This url is used both as success and failure url - url = URL_PREFIX + "resource_classes:detail" - resource_class_id = self.context["resource_class_id"] - return "%s?tab=resource_class_details__racks" % ( - urlresolvers.reverse(url, args=(resource_class_id,))) diff --git a/tuskar_ui/infrastructure/resource_management/tabs.py b/tuskar_ui/infrastructure/resource_management/tabs.py deleted file mode 100644 index 7273fea1..00000000 --- a/tuskar_ui/infrastructure/resource_management/tabs.py +++ /dev/null @@ -1,118 +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 _ # noqa - -from horizon import exceptions -from horizon import tabs - -from tuskar_ui import api as tuskar -from tuskar_ui.infrastructure.resource_management.racks\ - import tables as racks_tables -from tuskar_ui.infrastructure.resource_management.resource_classes\ - import tables as resource_classes_tables - - -def get_provision_racks_and_state(racks): - unprovisioned_racks = [rack for rack in racks - if not rack.is_provisioned] - provisioning_racks = [rack for rack in racks - if rack.is_provisioning] - if provisioning_racks: - state = 'provisioning' - elif unprovisioned_racks: - state = 'unprovisioned' - else: - state = 'provisioned' - return unprovisioned_racks, provisioning_racks, state - - -class ProvisioningInfoMixin(object): - def get_provisioning_racks_data(self): - try: - racks = tuskar.Rack.list(self.request) - except Exception: - racks = [] - exceptions.handle(self.request, _("Unable to retrieve racks.")) - return racks - - def get_context_data(self, request=None, **kwargs): - # XXX get_context_data has different signatures in different views - if request: - context = super(ProvisioningInfoMixin, self).get_context_data( - request, **kwargs) - else: - context = super(ProvisioningInfoMixin, self).get_context_data( - **kwargs) - (unprovisioned_racks, provisioning_racks, state) = ( - get_provision_racks_and_state(self. - get_provisioning_racks_data())) - context.update({ - 'unprovisioned_racks': unprovisioned_racks, - 'provisioning_racks': provisioning_racks, - 'provisioning_state': state, - }) - return context - - -class RacksTab(ProvisioningInfoMixin, tabs.TableTab): - table_classes = (racks_tables.RacksTable,) - name = _("Racks") - slug = "racks_tab" - template_name = ("infrastructure/resource_management/" - "racks/_index_table.html") - - def get_racks_data(self): - try: - racks = tuskar.Rack.list(self.request) - except Exception: - racks = [] - exceptions.handle(self.request, - _('Unable to retrieve racks.')) - return racks - - def get_context_data(self, request): - context = super(RacksTab, self).get_context_data(request) - try: - context["baremetal_nodes"] = tuskar.BaremetalNode.list_unracked( - self.request) - except Exception: - context["baremetal_nodes"] = [] - exceptions.handle(request, - _("Unable to retrieve baremetal nodes.")) - return context - - -class ResourceClassesTab(ProvisioningInfoMixin, tabs.TableTab): - table_classes = (resource_classes_tables.ResourceClassesTable,) - name = _("Classes") - slug = "resource_classes_tab" - template_name = ("infrastructure/resource_management/" - "resource_classes/_index_table.html") - #preload = False buggy, checkboxes doesn't work wit table actions - - def get_resource_classes_data(self): - try: - resource_classes = tuskar.ResourceClass.list(self.request) - except Exception: - resource_classes = [] - exceptions.handle(self.request, - _('Unable to retrieve resource classes list.')) - return resource_classes - - -class ResourceManagementTabs(tabs.TabGroup): - slug = "resource_management_tabs" - tabs = (ResourceClassesTab, RacksTab) - sticky = True diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/_provision.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/_provision.html deleted file mode 100644 index 04c920e8..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/_provision.html +++ /dev/null @@ -1,29 +0,0 @@ -{% extends "horizon/common/_modal_form.html" %} -{% load i18n %} -{% load url from future %} - -{% block form_id %}provision_form{% endblock %} -{% block form_action %}{% url 'horizon:infrastructure:resource_management:provision' %}{% endblock %} - -{% block modal_id %}provision_modal{% endblock %} -{% block modal-header %}{% trans "Provisioning Confirmation" %}{% endblock %} - -{% block modal-body %} -<div> - <p>{% trans "You are about to provision the following unprovisioned racks:" %} - <ol> - {% for rack in unprovisioned_racks %} - <li>{{ rack.name }}</li> - {% endfor %} - </ol></p> - <p>{% trans "This operation cannot be undone. Are you sure you want to do that?" %}</p> - <fieldset> - {% include "horizon/common/_form_fields.html" %} - </fieldset> -</div> -{% endblock %} - -{% block modal-footer %} - <input class="btn btn-primary" type="submit" value="{% trans "Provision" %}" /> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a> -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/_provision_info.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/_provision_info.html deleted file mode 100644 index 3fb8e0aa..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/_provision_info.html +++ /dev/null @@ -1,71 +0,0 @@ -{% load i18n %} -{% load url from future %} - -<div class="provisioning-state"> -{% if provisioning_state == "unprovisioned" %} - <div class="well well-small clearfix"> - <a class="btn btn-primary btn-small ajax-modal pull-right" - href="{% url 'horizon:infrastructure:resource_management:provision' %}"> - {% trans "Provision Deployment" %} - </a> - {% trans "Some racks are not provisioned yet." %} - </div> -{% endif %} -</div> - -<script> -// A global to make sure we only run this once. -var provisioning_state_initialized; - -(function () { - var init_check_state = function () { - if (provisioning_state_initialized) { - // Already initialized. - return; - }; - provisioning_state_initialized = true; - var divs = $('div.provisioning-state'); - var old_state = '{{ provisioning_state|escapejs }}'; - var url = '{% filter escapejs %}{% url "horizon:infrastructure:resource_management:provisioning_state" %}{% endfilter %}'; - var progress_html = '{% filter escapejs %}{% include "infrastructure/resource_management/_provision_progress.html" %}{% endfilter %}'; - var success_html = '<div class="alert alert-block alert-success"><a href="#" class="close" data-dismiss="alert">×</a>{% filter escapejs %}{% trans "Provisioning succeeded." %}{%endfilter %}</div>'; - var error_html = '<div class="alert alert-block alert-error"><a href="#" class="close" data-dismiss="alert">×</a>{% filter escapejs %}{% trans "Provisioning state unavailable." %}{% endfilter %}</div>'; - - var check_state = function () { - $.getJSON(url).done(function(data) { - var new_state = data['state']; - if (old_state === new_state) { - // Nothing to see here, move along. - return; - }; - if (new_state === 'provisioning') { - divs.html(progress_html); - } else if (old_state === 'provisioning') { - // Provisioning finished, don't poll anymore. - window.clearInterval(interval_id); - divs.html(success_html); - }; - old_state = new_state; - }).fail(function(jqxhr, textStatus, error) { - window.clearInterval(interval_id); - divs.html(error_html); - }); - }; - - if (old_state == 'provisioning') { - // Only display progress if js is enabled. - divs.html(progress_html); - }; - if (old_state !== 'provisioned') { - // Only poll when unprovisioned or provisioning. - var interval_id = window.setInterval(check_state, 20000); - }; - }; - - if (typeof($) !== 'undefined') { - $(init_check_state); - } else { - addHorizonLoadEvent(init_check_state); - } -}()); -</script> diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/_provision_progress.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/_provision_progress.html deleted file mode 100644 index 4989e8a1..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/_provision_progress.html +++ /dev/null @@ -1,8 +0,0 @@ -{% load i18n %} -<div class="well well-small clearfix"> - <div class="progress progress-striped active pull-right" - style="width:20%; margin: auto 0;"> - <div class="bar" style="width:100%"></div> - </div> - {% trans "Provisioning deployment…" %} -</div> diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/flavors/_detail_overview.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/flavors/_detail_overview.html deleted file mode 100644 index b0c97dc5..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/flavors/_detail_overview.html +++ /dev/null @@ -1,31 +0,0 @@ -{% load i18n sizeformat %} -{% load url from future %} - -<div class="info row-fluid detail"> - <div class="span4"> - <h4>{% trans "About" %}</h4> - <hr class="header_rule"> - <dl> - <dt>{% trans "Name" %}</dt> - <dd>{{ flavor.name|default:_("None") }}</dd> - <dt>{% trans "Resource Class" %}</dt> - <dd>{{ resource_class.name|default:_("None") }}</dd> - </dl> - </div> - <div class="span4"> - <h4>{% trans "Specification" %}</h4> - <hr class="header_rule"> - <dl> - <dt>{% trans "VCPU" %}</dt> - <dd>{{ flavor.cpu.value }}</dd> - <dt>{% trans "RAM" %}</dt> - <dd>{{ flavor.memory.value }} {{ flavor.memory.unit }}</dd> - <dt>{% trans "Root Disk" %}</dt> - <dd>{{ flavor.storage.value }} {{ flavor.storage.unit }}</dd> - <dt>{% trans "Ephemeral Disk" %}</dt> - <dd>{{ flavor.ephemeral_disk.value }} {{ flavor.ephemeral_disk.unit }}</dd> - <dt>{% trans "Swap Disk" %}</dt> - <dd>{{ flavor.swap_disk.value }} {{ flavor.swap_disk.unit }}</dd> - </dl> - </div> -</div> diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/flavors/detail.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/flavors/detail.html deleted file mode 100644 index 80229834..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/flavors/detail.html +++ /dev/null @@ -1,24 +0,0 @@ -{% extends 'infrastructure/base_detail.html' %} -{% load i18n %} -{% load url from future %} -{% block title %}{% trans "Flavor Detail"%}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Flavor Detail") %} -{% endblock page_header %} - -{% block actions %} -{% endblock %} - -{% block breadcrumbs %} - <div class="breadcrumbs"> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}?tab=resource_management_tabs__resource_classes_tab" >{% trans 'Home' %}</a> - <span class="separator"></span> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}?tab=resource_management_tabs__resource_classes_tab" >{% trans 'Classes'%}</a> - <span class="separator"></span> - <a href="{% url 'horizon:infrastructure:resource_management:resource_classes:detail' resource_class.id %}" >{{ resource_class.name }}</a> - <span class="separator"></span> - </div> -{% endblock breadcrumbs %} - -{% block name %}{{ flavor.name }}{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/index.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/index.html deleted file mode 100644 index 11d1d8ad..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/index.html +++ /dev/null @@ -1,25 +0,0 @@ -{% extends 'infrastructure/base.html' %} -{% load i18n %} -{% load url from future %} -{% block title %}{% trans "Resource Management" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Resource Management") %} -{% endblock page_header %} - -{% block main %} -<div class="row-fluid"> - <div class="span12"> - <div class="breadcrumbs"> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}?tab=resource_management_tabs__resource_classes_tab" >Home</a> - <span class="separator"></span> - </div> - </div> -</div> - -<div class="row-fluid"> - <div class="span12"> - {{ tab_group.render }} - </div> -</div> -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/_detail_overview.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/_detail_overview.html deleted file mode 100644 index b661b6ee..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/_detail_overview.html +++ /dev/null @@ -1,258 +0,0 @@ -{% load i18n sizeformat %} -{% load url from future %} -{% load chart_helpers %} - -<div class="info row-fluid detail"> - <div class="span4"> - <h4>{% trans "About" %}</h4> - <hr class="header_rule"> - <dl> - <dt>{% trans "MAC Address" %}</dt> - <dd>{{ baremetal_node.mac_address|default:_("None") }}</dd> - <dt>{% trans "IPs" %}</dt> - <dd>{{ baremetal_node.ip_address_other|default:_("None") }}</dd> - <dt>{% trans "Management IP" %}</dt> - <dd>{{ baremetal_node.pm_address|default:_("None") }}</dd> - <dt>{% trans "Power Management" %}</dt> - <dd>{{ tuskar_node.rack.power_management|default:_("-") }}</dd> - <dt>{% trans "Status" %}</dt> - <dd>{{ baremetal_node.status|default:_("None") }}</dd> - </dl> - </div> - <div class="span4"> - <h4>{% trans "Resource Assignment" %}</h4> - <hr class="header_rule"> - <dl> - <dt>{% trans "Rack" %}</dt> - {% if tuskar_node.rack %} - <dd><a href="{% url 'horizon:infrastructure:resource_management:racks:detail' tuskar_node.rack_id %}">{{ tuskar_node.rack.name|default:_("None") }}</a></dd> - {% else %} - <dd>{% trans "None" %}</dd> - {% endif %} - <!--<dt>{% trans "Region" %}</dt> - <dd>{{ tuskar_node.region|default:_("None") }}</dd>--> - <dt>{% trans "Node Type" %}</dt> - <dd>{{ tuskar_node.type|default:_("none") }}</dd> - <dt>{% trans "Provisioned Image" %}</dt> - <dd>{{ tuskar_node.image|default:_("None") }}</dd> - <dt>{% trans "Running Instances" %}</dt> - <dd>{{ running_instances }}</dd> - </dl> - </div> - <div class="span4"> - <h4>{% trans "Capacities" %}</h4> - <hr class="header_rule"> - <table class="capacities"> - <tr> - <td class="capacity_label">{% trans "CPU" %}:</td> - {% if tuskar_node.is_provisioned %} - <td> - <div id="cpu_capacity_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart" - data-capacity-limit="{{ tuskar_node.cpu.value }}" - data-capacity-used="{{ tuskar_node.cpu.usage }}" - data-average-capacity-used="{{ 2 }}"> - </div> - </td> - <td> - <a href="#" data-chart-type="modal_line_chart" data-url="/infrastructure/resource_management/racks/usage_data" data-series="cpu">{{ tuskar_node.cpu.usage }}/{{ tuskar_node.cpu.value }} {{ tuskar_node.cpu.unit }}</a> - </td> - {% else %} - <td> - <div id="cpu_capacity_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart"> - </div> - </td> - <td></td> - {% endif %} - </tr> - <tr> - <td class="capacity_label">{% trans "RAM" %}:</td> - {% if tuskar_node.is_provisioned %} - <td> - <div id="ram_capacity_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart" - data-capacity-limit="{{ tuskar_node.ram.value }}" - data-capacity-used="{{ tuskar_node.ram.usage }}" - data-average-capacity-used="{{ 12 }}"> - </div> - </td> - <td> - <a href="#" data-chart-type="modal_line_chart" data-url="/infrastructure/resource_management/racks/usage_data" data-series="ram">{{ tuskar_node.ram.usage }}/{{ tuskar_node.ram.value }} {{ tuskar_node.ram.unit }}</a> - </td> - {% else %} - <td> - <div id="ram_capacity_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart"> - </div> - </td> - <td></td> - {% endif %} - </tr> - <tr> - <td class="capacity_label">{% trans "Storage" %}:</td> - {% if tuskar_node.is_provisioned %} - <td> - <div id="storage_capacity_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart" - data-capacity-limit="{{ tuskar_node.storage.value }}" - data-capacity-used="{{ tuskar_node.storage.usage }}" - data-average-capacity-used="{{ 6 }}"> - </div> - </td> - <td> - <a href="#" data-chart-type="modal_line_chart" data-url="/infrastructure/resource_management/racks/usage_data" data-series="storage">{{ tuskar_node.storage.usage }}/{{ tuskar_node.storage.value }} {{ tuskar_node.storage.unit }}</a> - </td> - {% else %} - <td> - <div id="storage_capacity_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart"> - </div> - </td> - <td></td> - {% endif %} - </tr> - <tr> - <td class="capacity_label">{% trans "Network" %}:</td> - {% if tuskar_node.is_provisioned %} - <td> - <div id="network_capacity_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart" - data-capacity-limit="{{ tuskar_node.network.value }}" - data-capacity-used="{{ tuskar_node.network.usage }}" - data-average-capacity-used="{{ 40 }}"> - </div> - </td> - <td> - <a href="#" data-chart-type="modal_line_chart" data-url="/infrastructure/resource_management/racks/usage_data" data-series="network">{{ tuskar_node.network.usage }}/{{ tuskar_node.network.value }} {{ tuskar_node.network.unit }}</a> - </td> - {% else %} - <td> - <div id="network_capacity_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart"> - </div> - </td> - <td></td> - {% endif %} - </tr> - </table> - </div> -</div> - -<div class="row-fluid detail"> - <div class="span6"> - <h4>{% trans "Summary of Instances and Usage" %}</h4> - <hr class="header_rule"> - {% if tuskar_node.is_provisioned %} - <div> - <strong>{{ tuskar_node.running_instances }}</strong> instances - <strong>{{ tuskar_node.remaining_capacity }}%</strong> capacity remaining - </div> - <div class="flavor_usage_bar" - data-popup-free='{{ tuskar_node|remaining_capacity_by_flavors }}' - data-single-bar-orientation="horizontal" - data-single-bar-height="50" - data-single-bar-width="100%" - data-single-bar-used="{{ tuskar_node|all_used_instances }}" - data-single-bar-auto-scale-selector=".flavors_scale_selector" - data-single-bar-color-scale-range='["#000060", "#99FFFF"]'> - </div> - - <table class="flavor_usages"> - <tr> - {% for flavor in tuskar_node.list_flavors %} - <td class="flavor_usage_label"> - <a href="{% url 'horizon:infrastructure:resource_management:resource_classes:flavors:detail' tuskar_node.rack.resource_class.id flavor.id %}">{{ flavor.name }}</a> - </td> - {% endfor %} - </tr> - <tr> - {% for flavor in tuskar_node.list_flavors %} - <td> - <div class="flavor_usage_bar flavors_scale_selector" - data-popup-average='<p>Average capacity consumed by instances of {{flavor.name}} flavor in {{tuskar_node.name}} class.</p> - <p>{{ flavor.used_instances }}%, <strong>{{ flavor.used_instances }} instances</strong></p>' - data-single-bar-orientation="vertical" - data-single-bar-height="100%" - data-single-bar-width="40" - data-single-bar-used="{{ flavor.used_instances }}" - data-single-bar-average-used="{{ 50 }}" - data-single-bar-auto-scale-selector=".flavors_scale_selector" - data-single-bar-color-scale-range='["#000060", "#99FFFF"]'> - </div> - </td> - {% endfor %} - </tr> - <tr> - {% for flavor in tuskar_node.list_flavors %} - <td class="modal_chart flavor_usage_text"><a href="{{ "#" }}">{{ flavor.used_instances }}%</a></td> - {% endfor %} - </tr> - <tr> - {% for flavor in tuskar_node.list_flavors %} - <td class="flavor_usage_text">{{ flavor.used_instances }} inst.</td> - {% endfor %} - </tr> - </table> - - {% else %} - <p>{% trans "No data available yet." %}</p> - {% endif %} - </div> - - <div class="span6"> - <h4>{% trans "Active alerts" %}</h4> - <hr class="header_rule"> - {% if tuskar_node.is_provisioned %} - <ul> - {% for alert in tuskar_node.alerts %} - <li><i class="icon-warning-sign"></i>{{ alert.message }}</li> - {% endfor %} - </ul> - {% else %} - <p>{% trans "No data available yet." %}</p> - {% endif %} - </div> -</div> - -<div class="row-fluid detail"> - <div class="span6"> - <h4>{% trans "Top Communicating Nodes" %}</h4> - <hr class="header_rule"> - {% if tuskar_node.is_provisioned %} - <div class="communication_charts_wrapper"> - <div class="communication_chart_wrapper"> - <h5>The most contacting</h5> - <div id="most_contacting_racks" - class="communication_chart" - data-chart-type="circles_chart" - data-url="{% url 'horizon:infrastructure:resource_management:racks:top_communicating' tuskar_node.rack_id %}?cond=from" - data-time="now" - data-size="22"> - </div> - </div> - <div class="communication_chart_connection"></div> - <div class="communication_chart_wrapper"> - <h5>The most contacted</h5> - <div id="most_contacted_racks" - class="communication_chart" - data-chart-type="circles_chart" - data-url="{% url 'horizon:infrastructure:resource_management:racks:top_communicating' tuskar_node.rack.id %}?cond=to" - data-time="now" - data-size="22"> - </div> - </div> - </div> - {% else %} - <p>{% trans "No data available yet." %}</p> - {% endif %} - </div> -</div> diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/detail.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/detail.html deleted file mode 100644 index 1da1dd9d..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/detail.html +++ /dev/null @@ -1,25 +0,0 @@ -{% extends 'infrastructure/base_detail.html' %} -{% load i18n %} -{% load url from future %} -{% block title %}{% trans "Node Detail"%}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Node Detail") %} -{% endblock page_header %} - -{% block breadcrumbs %} - <div class="breadcrumbs"> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}?tab=resource_management_tabs__resource_classes_tab" >Home</a> - <span class="separator"></span> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}?tab=resource_management_tabs__racks_tab" >Racks</a> - <span class="separator"></span> - {% if tuskar_node %} - <a href="{% url 'horizon:infrastructure:resource_management:racks:detail' tuskar_node.rack_id %}">{{ tuskar_node.rack.name }}</a> - {% else %} - <a href="{% url 'horizon:infrastructure:resource_management:nodes:unracked' %}" >Unracked Nodes</a> - {% endif %} - <span class="separator"></span> - </div> -{% endblock breadcrumbs %} - -{% block name %}{{ baremetal_node.mac_address }}{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/unracked.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/unracked.html deleted file mode 100644 index 15c016ba..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/nodes/unracked.html +++ /dev/null @@ -1,30 +0,0 @@ -{% extends 'infrastructure/base.html' %} -{% load i18n %} -{% load url from future %} -{% block title %}{% trans "Resource Management" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Resource Management") %} -{% endblock page_header %} - - -{% block main %} -<div class="row-fluid"> - <div class="span12"> - <div class="breadcrumbs"> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}?tab=resource_management_tabs__resource_classes_tab" >Home</a> - <span class="separator"></span> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}?tab=resource_management_tabs__racks_tab" >Racks</a> - <span class="separator"></span> - </div> - - <h3>{% trans "Unracked Nodes" %}</h3> - </div> -</div> - -<div class="row-fluid"> - <div class="span12"> - {{ table.render }} - </div> -</div> -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/provision.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/provision.html deleted file mode 100644 index cc251c02..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/provision.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'infrastructure/base.html' %} -{% load i18n %} -{% block title %}{% trans "Start Provisioning Confirmation" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Provision Deployment") %} -{% endblock page_header %} - -{% block infrastructure_main %} - {% include "infrastructure/resource_management/_provision.html" %} -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_create.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_create.html deleted file mode 100644 index 491ad77d..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_create.html +++ /dev/null @@ -1,22 +0,0 @@ -{% extends "horizon/common/_modal_form.html" %} -{% load i18n %} -{% load url from future %} - -{% block form_id %}create_rack_form{% endblock %} -{% block form_action %}{% url 'horizon:infrastructure:resource_management:racks:create' %}{% endblock %} - -{% block modal_id %}create_rack_modal{% endblock %} -{% block modal-header %}{% trans "Create Rack" %}{% endblock %} - -{% block modal-body %} -<div> - <fieldset> - {% include "horizon/common/_form_fields.html" %} - </fieldset> -</div> -{% endblock %} - -{% block modal-footer %} - <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Rack" %}" /> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a> -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_detail_overview.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_detail_overview.html deleted file mode 100644 index 8bfd028b..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_detail_overview.html +++ /dev/null @@ -1,323 +0,0 @@ -{% load i18n sizeformat %} -{% load url from future %} -{% load chart_helpers %} - -{% if not rack.is_provisioned or rack.is_provisioning %} - <div class="info row-fluid detail"> - <div class="span12"> - <div data-state="{{rack.state}}" - data-url="{% url 'horizon:infrastructure:resource_management:racks:check_state' rack.id %}" - data-interval="20000" - class="overall-state provision-block"> - {% if not rack.is_provisioned %} - <div class="well clearfix"> - <p class="pull-right"> - {% trans "To make it ready to use," %} - <a href="{% url 'horizon:infrastructure:resource_management:index' %}?tab=resource_management_tabs__racks_tab"> - {% trans "provision your whole deployment." %} - </a> - </p> - {% trans "Rack is not provisioned yet." %} - </div> - {% endif %} - </div> - </div> - </div> -{% endif %} -<div class="info row-fluid detail"> - <div class="span4"> - <h4>{% trans "About" %}</h4> - <hr class="header_rule"> - <dl> - <dt>{% trans "IP Subnet" %}</dt> - <dd>{{ rack.subnet|default:_("None") }}</dd> - <dt>{% trans "Switch IPs" %}</dt> - <dd>{{ rack.switch_ips|default:_("None") }}</dd> - <dt>{% trans "Location" %}</dt> - <dd>{{ rack.location|default:_("None") }}</dd> - <dt>{% trans "State" %}</dt> - <dd>{{ rack.state|default:_("None") }}</dd> - </dl> - </div> - <div class="span4"> - <h4>{% trans "Resource Assignment" %}</h4> - <hr class="header_rule"> - <dl> - <dt>{% trans "Nodes" %}</dt> - <dd> - <a href="{% url 'horizon:infrastructure:resource_management:racks:detail' rack.id %}?tab=rack_detail_tabs__nodes"> - {{ rack.nodes_count|default:_("None") }} - </a> - </dd> - <dt>{% trans "Class" %}</dt> - <dd> - {% if rack.resource_class %} - <a href="{% url 'horizon:infrastructure:resource_management:resource_classes:detail' rack.resource_class_id %}"> - {{ rack.resource_class.name }} - </a> - {% else %} - {% trans "None" %} - {% endif %} - </dd> - <dt>{% trans "Class Image" %}</dt> - <dd>overcloud-compute</dd> {# FIXME It will eventually have to be not-hardcoded later #} - </dl> - </div> - <div class="span4"> - <h4>{% trans "Capacities" %}</h4> - <hr class="header_rule"> - {% if rack.capacities %} - <table class="capacities"> - {% for capacity in rack.capacities %} - <tr> - <td class="capacity_label">{{ capacity.name }}:</td> - {% if rack.is_provisioned %} - <td> - <div id="{{ capacity.name }}_capacity_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart" - data-capacity-limit="{{ capacity.value }}" - data-capacity-used="{{ capacity.usage }}" - data-average-capacity-used="{{ capacity.average }}"> - </div> - </td> - <td> - <a href="#" data-chart-type="modal_line_chart" data-url="/infrastructure/resource_management/racks/usage_data">{{ capacity.usage|default:_(" - ") }}/{{ capacity.value|default:_(" - ") }} {{ capacity.unit }}</a> - </td> - {% else %} - <td> - <div id="{{ capacity.name }}_capacity_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart"> - </div> - </td> - <td></td> - {% endif %} - </tr> - {% endfor %} - </table> - {% else %} - <p>No data available yet.</p> - {% endif %} - </div> -</div> - -<div class="info row-fluid detail"> - <div class="span6"> - <h4>{% trans "Summary of instances and Usage" %}</h4> - <hr class="header_rule"> - {% if rack.is_provisioned %} - <div> - <strong>{{ rack.total_instances }}</strong> instances - <strong>{{ rack.remaining_capacity }}%</strong> capacity remaining - </div> - - <div class="flavor_usage_bar" - data-popup-free='{{ rack|remaining_capacity_by_flavors }}' - data-single-bar-orientation="horizontal" - data-single-bar-height="35" - data-single-bar-width="100%" - data-single-bar-used="{{ rack|all_used_instances }}" - data-single-bar-auto-scale-selector=".flavors_scale_selector" - data-single-bar-color-scale-range='["#000060", "#99FFFF"]'> - </div> - - <table class="flavor_usages"> - <tr> - {% for flavor in rack.list_flavors %} - <td class="flavor_usage_label"> - <a href="{% url 'horizon:infrastructure:resource_management:resource_classes:flavors:detail' rack.resource_class.id flavor.id %}">{{ flavor.name }}</a> - </td> - {% endfor %} - </tr> - <tr> - {% for flavor in rack.list_flavors %} - <td> - <div class="flavor_usage_bar flavors_scale_selector" - data-popup-average='<p>Average capacity consumed by instances of {{flavor.name}} flavor in {{rack.name}} class.</p> - <p>{{ flavor.used_instances }}%, <strong>{{ flavor.used_instances }} instances</strong></p>' - data-single-bar-orientation="vertical" - data-single-bar-height="100%" - data-single-bar-width="30" - data-single-bar-used="{{ flavor.used_instances }}" - data-single-bar-average-used="{{ 50 }}" - data-single-bar-auto-scale-selector=".flavors_scale_selector" - data-single-bar-color-scale-range='["#000060", "#99FFFF"]'> - </div> - </td> - {% endfor %} - </tr> - <tr> - {% for flavor in rack.list_flavors %} - <td class="modal_chart flavor_usage_text"><a href="{{ "#" }}">{{ flavor.used_instances }}%</a></td> - {% endfor %} - </tr> - <tr> - {% for flavor in rack.list_flavors %} - <td class="flavor_usage_text">{{ flavor.used_instances }} inst.</td> - {% endfor %} - </tr> - </table> - {% else %} - <p>{% trans "No data available yet." %}</p> - {% endif %} - </div> - - <div class="span6 alerts"> - <h4>{% trans "Active Alerts" %}</h4> - <hr class="header_rule"> - {% if rack.is_provisioned %} - <ul> - {% for alert in rack.alerts %} - <li><i class="icon-warning-sign"></i>{{ alert.message }}</li> - {% endfor %} - {% for tuskar_node in rack.aggregated_alerts %} - <li> - <i class="icon-warning-sign"></i> - Node <a href="{% url 'horizon:infrastructure:resource_management:nodes:detail' tuskar_node.nova_baremetal_node_id %}">{{ tuskar_node.name }}</a> has some problems - </li> - {% endfor %} - </ul> - {% else %} - <p>{% trans "No data available yet." %}</p> - {% endif %} - </div> -</div> - -<div class="row-fluid"> - <div class="span6"> - <!-- FIXME Will be added later - <div class="circles_chart_time_picker"> - <select data-circles-chart-command="change_time" - data-receiver="#most_contacting_racks, #most_contacted_racks"> - <option value="now">Now</option> - <option value="yesterday">Yesterday</option> - <option value="last_week">Last Week</option> - <option value="last_month">Last Month</option> - </select> - </div> - --> - - <h4>Top Communicating Racks</h4> - <hr class="header_rule"> - <div class="clear"></div> - {% if rack.nodes_count and rack.is_provisioned %} - <div class="communication_charts_wrapper"> - <div class="communication_chart_wrapper"> - <h5>The most contacting</h5> - <div id="most_contacting_racks" - class="communication_chart" - data-chart-type="circles_chart" - data-url="{% url 'horizon:infrastructure:resource_management:racks:top_communicating' rack.id %}?cond=from" - data-time="now" - data-size="22"> - </div> - </div> - <div class="communication_chart_connection"></div> - <div class="communication_chart_wrapper"> - <h5>The most contacted</h5> - <div id="most_contacted_racks" - class="communication_chart" - data-chart-type="circles_chart" - data-url="{% url 'horizon:infrastructure:resource_management:racks:top_communicating' rack.id %}?cond=to" - data-time="now" - data-size="22"> - </div> - </div> - </div> - {% else %} - <p>No data available yet.</p> - {% endif %} - </div> - <div class="span6"> - <!-- FIXME Will be added later - <div class="circles_chart_time_picker"> - <select data-circles-chart-command="change_time" - data-receiver="#rack_health_chart"> - <option value="now">Now</option> - <option value="yesterday">Yesterday</option> - <option value="last_week">Last Week</option> - <option value="last_month">Last Month</option> - </select> - </div> - --> - - <h4>Node health</h4> - {% if rack.nodes_count and rack.is_provisioned %} - - <ul class="nav nav-tabs" - data-circles-chart-command="change_url" - data-receiver="#rack_health_chart"> - <li class="active"> - <a data-url="{% url 'horizon:infrastructure:resource_management:racks:node_health' rack.id %}?type=overall_health" href="#"> - Overall Health</a> - </li> - <li> - <a data-url="{% url 'horizon:infrastructure:resource_management:racks:node_health' rack.id %}?type=alerts" href="#"> - Alerts</a> - </li> - <li> - <a data-url="{% url 'horizon:infrastructure:resource_management:racks:node_health' rack.id %}?type=capacities" href="#"> - Capacities</a> - </li> - <li> - <a data-url="{% url 'horizon:infrastructure:resource_management:racks:node_health' rack.id %}?type=status" href="#"> - Status</a> - </li> - </ul> - <div id ="rack_health_chart" - class="health_chart" - data-chart-type="circles_chart" - data-url="{% url 'horizon:infrastructure:resource_management:racks:node_health' rack.id %}" - data-time="now" - data-size="22"> - </div> - {% else %} - <hr class="header_rule"> - <div class="clear"></div> - - <p>No data available yet.</p> - {% endif %} - </div> -</div> - - -<script type="text/javascript"> -/* polling of status. */ -horizon.detail_overview = { - update: function () { - var state_obj = $('.overall-state').first(); - var state = state_obj.data('state'); - var interval = state_obj.data('interval'); - var url = state_obj.data('url'); - if (state == 'provisioning') { - // Wait and try to update again in next interval instead - setTimeout(horizon.detail_overview.update, interval); - - this.jqxhr = $.getJSON( url, function() { - state_obj.html('{% filter escapejs %}{% include "infrastructure/resource_management/_provision_progress.html" %}{% endfilter %}'); - }) - .done(function(data) { - // FIXME find a way how to only update graph with new data - // not delete and create - if (data['state'] != 'provisioning'){ - window.location.reload(); - } - }) - .fail(function() { - // FIXME add proper fail message - console.log( "error" ); - }) - .always(function() { - // FIXME add behaviour that should be always done - }); - } - } -}; - - -horizon.addInitFunction(function () { - horizon.detail_overview.update(); -}); - -</script> diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_edit.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_edit.html deleted file mode 100644 index 87ccb864..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_edit.html +++ /dev/null @@ -1,22 +0,0 @@ -{% extends "horizon/common/_modal_form.html" %} -{% load i18n %} -{% load url from future %} - -{% block form_id %}edit_rack_form{% endblock %} -{% block form_action %}{% url 'horizon:infrastructure:resource_management:racks:edit' rack_id %}{% endblock %} - -{% block modal_id %}edit_rack_modal{% endblock %} -{% block modal-header %}{% trans "Edit Rack" %}{% endblock %} - -{% block modal-body %} -<div> - <fieldset> - {% include "horizon/common/_form_fields.html" %} - </fieldset> -</div> -{% endblock %} - -{% block modal-footer %} - <input class="btn btn-primary pull-right" type="submit" value="{% trans "Save" %}" /> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a> -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_edit_status.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_edit_status.html deleted file mode 100644 index f2a81170..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_edit_status.html +++ /dev/null @@ -1,23 +0,0 @@ -{% extends "horizon/common/_modal_form.html" %} -{% load i18n %} -{% load url from future %} - -{% block form_id %}edit_rack_status_form{% endblock %} -{% block form_action %}{% url 'horizon:infrastructure:resource_management:racks:edit_status' rack_id %}?action={{ action }}{% endblock %} - -{% block modal_id %}edit_rack_status_modal{% endblock %} -{% block modal-header %}{% trans "Rack Action Confirmation" %}{% endblock %} - -{% block modal-body %} -<div> - {% trans "Are you sure?" %} - <fieldset> - {% include "horizon/common/_form_fields.html" %} - </fieldset> -</div> -{% endblock %} - -{% block modal-footer %} - <input class="btn btn-primary" type="submit" value="{% trans "Yes" %}" /> - <a href="{% url 'horizon:infrastructure:resource_management:racks:detail' rack_id %}" class="btn secondary cancel close">{% trans "Cancel" %}</a> -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_index_table.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_index_table.html deleted file mode 100644 index 66f5116c..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_index_table.html +++ /dev/null @@ -1,4 +0,0 @@ -{% load i18n %} -{% include "infrastructure/resource_management/_provision_info.html" with provisioning_state=provisioning_state %} -{{ racks_table.render }} -<a href="{% url 'horizon:infrastructure:resource_management:nodes:unracked' %}">{% trans "View Unracked Nodes"%} ({{baremetal_nodes|length}})</a> diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_rack_nodes_step.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_rack_nodes_step.html deleted file mode 100644 index 3e0cbf1b..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_rack_nodes_step.html +++ /dev/null @@ -1,17 +0,0 @@ -<noscript><h3>{{ step }}</h3></noscript> -<table class="table-fixed"> - <tbody> - <tr> - <td class="actions"> - {% include "horizon/common/_form_fields.html" %} - </td> - <td class="help_text"> - {{ step.get_help_text }} - </td> - </tr> - </tbody> -</table> - -<div id="nodes-formset-datatable"> - {{ nodes_table.render }} -</div> diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_upload.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_upload.html deleted file mode 100644 index 44097d3d..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/_upload.html +++ /dev/null @@ -1,37 +0,0 @@ -{% extends "horizon/common/_modal_form.html" %} -{% load i18n %} -{% load url from future %} - -{% block form_id %}upload_rack_form{% endblock %} -{% block form_action %}{% url 'horizon:infrastructure:resource_management:racks:upload' %}{% endblock %} -{% block form_attrs %}enctype="multipart/form-data"{% endblock %} - -{% block modal_id %}upload_rack_modal{% endblock %} -{% block modal-header %}{% trans "Upload Rack" %}{% endblock %} - -{% block modal-body %} - <div> - <fieldset> - <span class="control-group clearfix error"> - {% if form.csv_file.errors %} - <div class="error help-inline">{{ form.csv_file.errors }}</div> - {% endif %} - </span> - {{ form.csv_file }} - <input class="btn btn-primary pull-right always-enabled" type="submit" name=upload value="{% trans "Upload File" %}" /> - <div class="help-block"> - CSV file format:<br>rack name,resource class name,subnet,region,list of mac addresses separated by space - </div> - {{ form.uploaded_data }} - </fieldset> - </div> - <div class="csv_rack_table"> - {% trans "Uploaded racks, which you are going to add to the system:" %} - {{ racks_table.render }} - </div> -{% endblock %} - -{% block modal-footer %} -<input class="btn btn-primary pull-right always-enabled" type="submit" name=add_racks value="{% trans "Add Racks" %}" {% if not form.uploaded_data.value %}disabled{% endif %}/> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a> -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/create.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/create.html deleted file mode 100644 index 9ad42b2d..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/create.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'infrastructure/base.html' %} -{% load i18n %} -{% block title %}{% trans "Create Rack" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Create Rack") %} -{% endblock page_header %} - -{% block infrastructure_main %} - {% include "infrastructure/resource_management/racks/_create.html" %} -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/detail.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/detail.html deleted file mode 100644 index 8ac1cfa4..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/detail.html +++ /dev/null @@ -1,60 +0,0 @@ -{% extends 'infrastructure/base_detail.html' %} -{% load i18n %} -{% load url from future %} -{% block title %}{% trans "Rack Detail"%}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Rack Detail") %} -{% endblock page_header %} - -{% block breadcrumbs %} - <div class="breadcrumbs"> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}?tab=resource_management_tabs__resource_classes_tab" >Home</a> - <span class="separator"></span> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}?tab=resource_management_tabs__racks_tab" >Racks</a> - <span class="separator"></span> - </div> -{% endblock breadcrumbs %} - -{% block name %}{{ rack.name }}{% endblock %} - -{% block actions %} - <div class="btn-group"> - {% if rack.is_provisioned %} - <a class="btn ajax-modal" href="{% url 'horizon:infrastructure:resource_management:racks:edit_status' rack.id %}?action=unprovision">{% trans "Unprovision Rack" %}</a> - {% endif %} - </div> - {# <div class="btn-group"> #} - {# <a class="btn ajax-modal" href="{% url 'horizon:infrastructure:resource_management:racks:edit_status' rack.id %}?action=start">{% trans "Start" %}</a> #} - {# <a class="btn ajax-modal" href="{% url 'horizon:infrastructure:resource_management:racks:edit_status' rack.id %}?action=reboot">{% trans "Reboot" %}</a> #} - {# <a class="btn ajax-modal" href="{% url 'horizon:infrastructure:resource_management:racks:edit_status' rack.id %}?action=shutdown">{% trans "Shutdown" %}</a> #} - {# </div> #} - <div class="btn-group"> - <a class="btn ajax-modal" href="{% url 'horizon:infrastructure:resource_management:racks:detail_edit' rack.id %}">{% trans "Edit" %}</a> - </div> -{% endblock %} - -{% block overall_usage %} - <table class="capacities overall_usage"> - <tr> - <td class="capacity_label">{% trans "Usage" %}:</td> - <td> - {% if rack.is_provisioned %} - <div id="rack_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart" - data-capacity-limit="{{ rack.vm_capacity.value }}" - data-capacity-used="{{ rack.vm_capacity.usage }}" - data-average-capacity-used="{{ rack.vm_capacity.average }}"> - </div> - {% else %} - <div id="rack_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart"> - </div> - {% endif %} - </td> - </tr> - </table> -{% endblock %} - diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/edit.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/edit.html deleted file mode 100644 index 76a8e439..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/edit.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'infrastructure/base.html' %} -{% load i18n %} -{% block title %}{% trans "Edit Rack" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Edit Rack") %} -{% endblock page_header %} - -{% block infrastructure_main %} - {% include "infrastructure/resource_management/racks/_edit.html" %} -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/edit_status.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/edit_status.html deleted file mode 100644 index 99789380..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/edit_status.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'infrastructure/base.html' %} -{% load i18n %} -{% block title %}{% trans "Rack Action Confirmation" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Edit Rack Status") %} -{% endblock page_header %} - -{% block infrastructure_main %} - {% include "infrastructure/resource_management/racks/_edit_status.html" %} -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/upload.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/upload.html deleted file mode 100644 index 1df9454d..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/racks/upload.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'infrastructure/base.html' %} -{% load i18n %} -{% block title %}{% trans "Upload Rack" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Upload Rack") %} -{% endblock page_header %} - -{% block main %} - {% include "infrastructure/resource_management/racks/_upload.html" %} -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_action.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_action.html deleted file mode 100644 index 5f7108ea..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_action.html +++ /dev/null @@ -1,22 +0,0 @@ -{% extends "horizon/common/_modal_form.html" %} -{% load i18n %} -{% load url from future %} -{% block form_id %}resource_class_action_form{% endblock %} -{% block form_action %} - {% url 'horizon:infrastructure:resource_management:resource_classes:detail_action' resource_class_id %}?action={{ action }} -{% endblock %} -{% block modal_id %}resource_class_action_modal{% endblock %} -{% block modal-header %}{{header}}{% endblock %} -{% block modal-body %} -<div> - {% trans "Are you sure?" %} - <fieldset> - {% include "horizon/common/_form_fields.html" %} - </fieldset> -</div> -{% endblock %} -{% block modal-footer %} - <input class="btn btn-primary" type="submit" value="{% trans "Yes" %}" /> - <a href="{% url 'horizon:infrastructure:resource_management:resource_classes:detail' resource_class_id %}" - class="btn secondary cancel close">{% trans "Cancel" %}</a> -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_detail_flavors.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_detail_flavors.html deleted file mode 100644 index 34226ea9..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_detail_flavors.html +++ /dev/null @@ -1 +0,0 @@ -{{ flavors_table_table.render }} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_detail_overview.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_detail_overview.html deleted file mode 100644 index 6eec6751..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_detail_overview.html +++ /dev/null @@ -1,239 +0,0 @@ -{% load i18n sizeformat %} -{% load url from future %} -{% load chart_helpers %} - -<div class="status row-fluid detail"> - <div class="span4"> - <h4>{% trans "About" %}</h4> - <hr class="header_rule"> - <dl> - <dt>{% trans "Racks" %}</dt> - <dd><a href="?tab=resource_class_details__racks" >{{ resource_class.list_racks|length }} {% trans "racks" %}</a></dd> - <dt>{% trans "Nodes" %}</dt> - <dd>{{ resource_class.tuskar_nodes|length }} {% trans "nodes" %}</dd> - </dl> - </div> - - <div class="span4"> - <h4>{% trans "Provided Service" %}</h4> - <hr class="header_rule"> - <dl> - <dt>{% trans "Type" %}</dt> - <dd>{{ resource_class.service_type }}</dd> - <dt>{% trans "Flavors" %}</dt> - <dd><a href="?tab=resource_class_details__flavors" >{{ resource_class.list_flavors|length }} {% trans "flavors" %}</a></dd> - <dd></dd> - <dt>{% trans "Active Instances" %}</dt> - <dd>{{ resource_class.running_virtual_machines|length }} {% trans "instances" %}</dd> - </dl> - </dl> - </div> - - <div class="span4"> - <h4>{% trans "Capacities" %}</h4> - <hr class="header_rule"> - {% if resource_class.capacities %} - <table class="capacities"> - {% for capacity in resource_class.capacities %} - <tr> - {% if resource_class.has_provisioned_rack %} - <td class="capacity_label">{{ capacity.name }}:</td> - <td> - <div id="{{ capacity.name }}_capacity_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart" - data-capacity-limit="{{ capacity.value }}" - data-capacity-used="{{ capacity.usage }}" - data-average-capacity-used="{{ capacity.average }}"> - </div> - </td> - <td> - <a href="#" data-chart-type="modal_line_chart" data-url="/infrastructure/resource_management/racks/usage_data" data-series="{{ capacity.name }}">{{ capacity.usage|default:_(" - ") }}/{{ capacity.value|default:_(" - ") }} {{ capacity.unit }}</a> - </td> - {% else %} - <td> - <div id="{{ capacity.name }}_capacity_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart"> - </div> - </td> - <td></td> - {% endif %} - </tr> - {% endfor %} - </table> - {% else %} - <p>No data available yet.</p> - {% endif %} - </div> -</div> - -<div class="status row-fluid detail"> - <div class="span6"> - <h4>{% trans "Capacity Usage" %}</h4> - <hr class="header_rule"> - {% if resource_class.has_provisioned_rack %} - <div data-chart-type="line_chart" data-url="/infrastructure/resource_management/racks/usage_data" data-series="cpu,ram,storage,network"></div> - {% else %} - <p>{% trans "No data available yet." %}</p> - {% endif %} - </div> - - <div class="span6 alerts"> - <h4>{% trans "Active Alerts" %}</h4> - <hr class="header_rule"> - {% if resource_class.has_provisioned_rack %} - <ul> - {% for rack in resource_class.aggregated_alerts %} - <li> - <i class="icon-warning-sign"></i> - Rack <a href="{% url 'horizon:infrastructure:resource_management:racks:detail' rack.id %}">{{ rack.name }}</a> has some problems - </li> - {% endfor %} - </ul> - {% else %} - <p>{% trans "No data available yet." %}</p> - {% endif %} - </div> -</div> - -<div class="row-fluid detail"> - <div class="span6"> - <h4>{% trans "Summary of Instances and Usage" %}</h4> - <hr class="header_rule"> - {% if resource_class.has_provisioned_rack %} - <!-- - <dl> - {% for flavor in resource_class.running_virtual_machines %} - <dt>{{ flavor.name }}</dt> - <dd>{{ flavor.max_vms|default:_(" - ") }}</dd> - {% endfor %} - </dl> - --> - - <div class="clear"></div> - <div> - <strong>{{ resource_class.total_instances }}</strong> instances - <strong>{{resource_class.remaining_capacity}}%</strong> capacity remaining - </div> - <div class="flavor_usage_bar" - data-popup-free='{{resource_class|remaining_capacity_by_flavors}}' - data-single-bar-orientation="horizontal" - data-single-bar-height="35" - data-single-bar-width="100%" - data-single-bar-used="{{ resource_class|all_used_instances }}" - data-single-bar-auto-scale-selector=".flavors_scale_selector" - data-single-bar-color-scale-range='["#000060", "#99FFFF"]' - > - </div> - - <table class="flavor_usages"> - <tr> - {% for flavor in resource_class.list_flavors %} - <td class="flavor_usage_label"> - {{ flavor.name }} - </td> - {% endfor %} - </tr> - <tr> - {% for flavor in resource_class.list_flavors %} - <td> - <div - class="flavor_usage_bar flavors_scale_selector" - data-popup-average=' - <p>Average capacity consumed by instances of {{flavor.name}} flavor in {{resource_class.name}} class.</p> - <p>{{ flavor.used_instances }}%, <strong>{{ flavor.used_instances }} instances</strong></p> - ' - data-single-bar-orientation="vertical" - data-single-bar-height="100%" - data-single-bar-width="30" - data-single-bar-used="{{ flavor.used_instances }}" - data-single-bar-average-used="{{ 50 }}" - data-single-bar-auto-scale-selector=".flavors_scale_selector" - data-single-bar-color-scale-range='["#000060", "#99FFFF"]' - > - </div> - </td> - {% endfor %} - </tr> - <tr> - {% for flavor in resource_class.list_flavors %} - <td class="modal_chart flavor_usage_text"><a href="{{ "#" }}">{{ flavor.used_instances }}%</a></td> - {% endfor %} - </tr> - <tr> - {% for flavor in resource_class.list_flavors %} - <td class="flavor_usage_text">{{ flavor.used_instances }} inst.</td> - {% endfor %} - </tr> - </table> - {% else %} - <p>{% trans "No data available yet." %}</p> - {% endif %} - </div> - - <div class="span6"> - <!-- FIXME Will be added later - <div class="circles_chart_time_picker"> - <select data-circles-chart-command="change_time" - data-receiver=".rack_health_chart"> - <option value="now">Now</option> - <option value="yesterday">Yesterday</option> - <option value="last_week">Last Week</option> - <option value="last_month">Last Month</option> - </select> - </div> - --> - - <h4>Rack health</h4> - - {% if resource_class.has_provisioned_rack %} - <ul class="nav nav-tabs" - data-circles-chart-command="change_url" - data-receiver=".rack_health_chart"> - <li class="active"> - <a data-url="{% url 'horizon:infrastructure:resource_management:resource_classes:rack_health' resource_class.id %}?type=overall_health" href="#"> - Overall Health</a> - </li> - <li> - <a data-url="{% url 'horizon:infrastructure:resource_management:resource_classes:rack_health' resource_class.id %}?type=alerts" href="#"> - Alerts</a> - </li> - <li> - <a data-url="{% url 'horizon:infrastructure:resource_management:resource_classes:rack_health' resource_class.id %}?type=capacities" href="#"> - Capacities</a> - </li> - <li> - <a data-url="{% url 'horizon:infrastructure:resource_management:resource_classes:rack_health' resource_class.id %}?type=status" href="#"> - Status</a> - </li> - </ul> - <!--<h5>Region 1<h5> - <div class="rack_health_chart" - data-chart-type="circles_chart" - data-url="/infrastructure/racks/1/top_communicating.json?region=1" - data-region=1 //// implement region parameter - data-time="now" - data-size="10"> - </div> - <h5>Region 2<h5> - <div class="rack_health_chart" - data-chart-type="circles_chart" - data-url="/infrastructure/racks/1/top_communicating.json?region=2" - data-region=1 //// implement region parameter - data-time="now" - data-size="10"> - </div> - <h5>Region 3<h5>--> - <div class="rack_health_chart" - data-chart-type="circles_chart" - data-url="{% url 'horizon:infrastructure:resource_management:resource_classes:rack_health' resource_class.id %}" - data-time="now" - data-size="22"> - </div> - {% else %} - <hr class="header_rule"> - <p>{% trans "No data available yet." %}</p> - {% endif %} - </div> -</div> diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_detail_racks.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_detail_racks.html deleted file mode 100644 index b5d73097..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_detail_racks.html +++ /dev/null @@ -1 +0,0 @@ -{{ racks_table_table.render }} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_flavors_step.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_flavors_step.html deleted file mode 100644 index a75c6d9f..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_flavors_step.html +++ /dev/null @@ -1,35 +0,0 @@ -{% extends "infrastructure/resource_management/resource_classes/_table_step.html" %} -{% block table_step %} - <div id="flavors-table-block"> - {{ block.super }} - </div> - <script> - (window.$ || window.addHorizonLoadEvent)(function () { - 'use strict'; - - var $select = $('select#id_service_type'), - $table_block = $('#flavors-table-block'), - $tab = $( - 'a[data-target="#create_resource_class__' + - 'resourceclassflavorsaction"], ' + - 'a[data-target="#update_resource_class__' + - 'resourceclassflavorsaction"]' - ).parent('li'); - - $select.change(function () { - if ($select.val() === 'compute') { - $table_block.show(); - $tab.show(300); - } else { - $table_block.hide(); - $tab.hide(300); - }; - }); - - if ($select.val() !== 'compute') { - $table_block.hide(); - $tab.hide(); - }; - }); - </script> -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_index_table.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_index_table.html deleted file mode 100644 index e60ecb26..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_index_table.html +++ /dev/null @@ -1,3 +0,0 @@ -{% load i18n %} -{% include "infrastructure/resource_management/_provision_info.html" with provisioning_state=provisioning_state %} -{{ table.render }} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_table_step.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_table_step.html deleted file mode 100644 index 55bfb116..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/_table_step.html +++ /dev/null @@ -1,5 +0,0 @@ -{% block table_step %} -<noscript><h3>{{ step }}</h3></noscript> - -{{ table.render }} -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/action.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/action.html deleted file mode 100644 index c2b03cf1..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/action.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends 'infrastructure/base.html' %} -{% load i18n %} -{% block title %}{% trans "Resource Class Action Confirmation" %}{% endblock %} -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Resource Class Action") %} -{% endblock page_header %} -{% block infrastructure_main %} - {% include "infrastructure/resource_management/resource_classes/_edit_status.html" %} -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/detail.html b/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/detail.html deleted file mode 100644 index 4a1047d1..00000000 --- a/tuskar_ui/infrastructure/resource_management/templates/resource_management/resource_classes/detail.html +++ /dev/null @@ -1,63 +0,0 @@ -{% extends 'infrastructure/base_detail.html' %} -{% load i18n sizeformat %} -{% load url from future %} -{% block title %}{% trans "Resource Class Detail" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title="Resource Class Detail" %} -{% endblock page_header %} - -{% block breadcrumbs %} - <div class="breadcrumbs"> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}?tab=resource_management_tabs__resource_classes_tab" >Home</a> - <span class="separator"></span> - <a href="{% url 'horizon:infrastructure:resource_management:index' %}?tab=resource_management_tabs__resource_classes_tab" >Classes</a> - <span class="separator"></span> - </div> -{% endblock breadcrumbs %} - -{% block name %}{{ resource_class.name }}{% endblock %} - -{% block actions %} - <div class="btn-group"> - <a class="btn ajax-modal" - href="{% url 'horizon:infrastructure:resource_management:resource_classes:detail_update' resource_class.id %}"> - {% trans "Edit" %} - </a> - <a {% if resource_class.deletable %} - class="btn ajax-modal" - href="{% url 'horizon:infrastructure:resource_management:resource_classes:detail_action' resource_class.id %}?action=delete" - {% else %} - title="{% trans "Resource Class contains racks and can't be deleted." %}" - class="btn disabled" - href="#" - {% endif %} - > - {% trans "Delete" %} - </a> - </div> -{% endblock %} - - -{% block overall_usage %} - <table class="capacities overall_usage"> - <tr> - <td class="capacity_label">{% trans "Usage" %}:</td> - <td> - {% if resource_class.has_provisioned_rack %} - <div id="resource_class_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart" - data-capacity-limit="{{ resource_class.vm_capacity.value }}" - data-capacity-used="{{ resource_class.vm_capacity.usage }}"> - </div> - {% else %} - <div id="resource_class_usage" - class="capacity_bar" - data-chart-type="capacity_bar_chart"> - </div> - {% endif %} - </td> - </tr> - </table> -{% endblock %} diff --git a/tuskar_ui/infrastructure/resource_management/tests.py b/tuskar_ui/infrastructure/resource_management/tests.py deleted file mode 100644 index ef876124..00000000 --- a/tuskar_ui/infrastructure/resource_management/tests.py +++ /dev/null @@ -1,95 +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.core import urlresolvers -from django import http - -import mox - -from tuskar_ui import api as tuskar -from tuskar_ui.test import helpers as test - - -class ResourceManagementTests(test.BaseAdminViewTests): - index_page = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index') - - def setUp(self): - super(ResourceManagementTests, self).setUp() - - @test.create_stubs({ - tuskar.ResourceClass: ('get', 'list', 'list_racks', 'tuskar_nodes'), - tuskar.TuskarNode: ('list',), - tuskar.Rack: ('list',), - }) - def test_index(self): - - # ResourceClass stubs - resource_classes = self.tuskar_resource_classes.list() - resource_class = self.tuskar_resource_classes.first() - tuskar_nodes = [] - racks = [] - - tuskar.ResourceClass.tuskar_nodes = tuskar_nodes - tuskar.ResourceClass.list_racks = racks - - tuskar.Rack.list(mox.IsA(http.HttpRequest)).AndReturn(racks) - tuskar.ResourceClass.list( - mox.IsA(http.HttpRequest)).AndReturn(resource_classes) - - tuskar.ResourceClass.get( - mox.IsA(http.HttpRequest), - resource_class.id).AndReturn(resource_class) - # ResourceClass stubs end - - # Rack stubs - racks = self.tuskar_racks.list() - - tuskar.Rack.list(mox.IsA(http.HttpRequest)).AndReturn(racks) - tuskar.Rack.list(mox.IsA(http.HttpRequest)).AndReturn(racks) - tuskar.TuskarNode.list( - mox.IsA(http.HttpRequest)).AndReturn(tuskar_nodes) - # Rack stubs end - - self.mox.ReplayAll() - - url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index') - res = self.client.get(url) - self.assertTemplateUsed( - res, 'infrastructure/resource_management/index.html') - - # ResourceClass asserts - self.assertItemsEqual(res.context['resource_classes_table'].data, - resource_classes) - # ResourceClass asserts end - - # Rack asserts - self.assertItemsEqual(res.context['racks_table'].data, racks) - # Rack asserts end - - @test.create_stubs({tuskar.Rack: ('provision_all',)}) - def test_provision_post(self): - tuskar.Rack.provision_all(mox.IsA(http.HttpRequest)) - - self.mox.ReplayAll() - - url = urlresolvers.reverse('horizon:infrastructure:' - 'resource_management:provision', - args=[]) - response = self.client.post(url) - - self.assertNoFormErrors(response) - self.assertMessageCount(success=1) - self.assertRedirectsNoFollow(response, self.index_page) diff --git a/tuskar_ui/infrastructure/resource_management/urls.py b/tuskar_ui/infrastructure/resource_management/urls.py deleted file mode 100644 index 9a5c7621..00000000 --- a/tuskar_ui/infrastructure/resource_management/urls.py +++ /dev/null @@ -1,45 +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 import conf -from django.conf.urls import defaults - -from tuskar_ui.infrastructure.resource_management.nodes\ - import urls as node_urls -from tuskar_ui.infrastructure.resource_management.racks\ - import urls as rack_urls -from tuskar_ui.infrastructure.resource_management.resource_classes\ - import urls as resource_classes_urls -from tuskar_ui.infrastructure.resource_management import views -from tuskar_ui.test import urls as test_urls - - -urlpatterns = defaults.patterns( - '', - defaults.url(r'^$', views.IndexView.as_view(), name='index'), - defaults.url(r'^provision$', views.ProvisionView.as_view(), - name='provision'), - defaults.url(r'^provisioning_state.json$', views.provisioning_state, - name='provisioning_state'), - defaults.url(r'^racks/', defaults.include(rack_urls, namespace='racks')), - defaults.url(r'^resource_classes/', - defaults.include(resource_classes_urls, - namespace='resource_classes')), - defaults.url(r'^nodes/', defaults.include(node_urls, namespace='nodes')), -) - -if conf.settings.DEBUG: - urlpatterns += defaults.patterns( - '', defaults.url(r'^qunit$', - defaults.include(test_urls, namespace='tests'))) diff --git a/tuskar_ui/infrastructure/resource_management/views.py b/tuskar_ui/infrastructure/resource_management/views.py deleted file mode 100644 index acc5a141..00000000 --- a/tuskar_ui/infrastructure/resource_management/views.py +++ /dev/null @@ -1,52 +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. - -""" -Views for Resource Management. -""" - -from django.core import urlresolvers -from django import http -from django.utils import simplejson - -from horizon import forms as horizon_forms -from horizon import tabs as horizon_tabs - -from tuskar_ui import api as tuskar -from tuskar_ui.infrastructure.resource_management import forms -from tuskar_ui.infrastructure.resource_management import tabs - - -class IndexView(horizon_tabs.TabbedTableView): - tab_group_class = tabs.ResourceManagementTabs - template_name = 'infrastructure/resource_management/index.html' - - -class ProvisionView(tabs.ProvisioningInfoMixin, horizon_forms.ModalFormView): - form_class = forms.Provision - template_name = 'infrastructure/resource_management/provision.html' - - def get_success_url(self): - # Redirect to previous URL - default_url = urlresolvers.reverse( - 'horizon:infrastructure:resource_management:index') - return self.request.META.get('HTTP_REFERER', default_url) - - -def provisioning_state(request, rack_id=None): - racks = tuskar.Rack.list(request) - (unprovisioned_racks, provisioning_racks, - state) = tabs.get_provision_racks_and_state(racks) - return http.HttpResponse(simplejson.dumps({'state': state}), - mimetype="application/json") diff --git a/tuskar_ui/infrastructure/resources_archived/__init__.py b/tuskar_ui/infrastructure/resources_archived/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tuskar_ui/infrastructure/resources_archived/__init__.py diff --git a/tuskar_ui/infrastructure/resources_archived/panel.py b/tuskar_ui/infrastructure/resources_archived/panel.py new file mode 100644 index 00000000..1b0477f9 --- /dev/null +++ b/tuskar_ui/infrastructure/resources_archived/panel.py @@ -0,0 +1,27 @@ +# -*- 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 _ # noqa + +import horizon + +from tuskar_ui.infrastructure import dashboard + + +class ResourcesArchived(horizon.Panel): + name = _("Archived") + slug = "resources_archived" + + +dashboard.Infrastructure.register(ResourcesArchived) diff --git a/tuskar_ui/infrastructure/resources_archived/urls.py b/tuskar_ui/infrastructure/resources_archived/urls.py new file mode 100644 index 00000000..d4258572 --- /dev/null +++ b/tuskar_ui/infrastructure/resources_archived/urls.py @@ -0,0 +1,23 @@ +# -*- 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.resources_archived import views + + +urlpatterns = defaults.patterns( + '', + defaults.url(r'^$', views.IndexView.as_view(), name='index'), +) diff --git a/tuskar_ui/infrastructure/resources_archived/views.py b/tuskar_ui/infrastructure/resources_archived/views.py new file mode 100644 index 00000000..f046b626 --- /dev/null +++ b/tuskar_ui/infrastructure/resources_archived/views.py @@ -0,0 +1,18 @@ +# -*- 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' diff --git a/tuskar_ui/infrastructure/resources_management/__init__.py b/tuskar_ui/infrastructure/resources_management/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tuskar_ui/infrastructure/resources_management/__init__.py diff --git a/tuskar_ui/infrastructure/resources_management/panel.py b/tuskar_ui/infrastructure/resources_management/panel.py new file mode 100644 index 00000000..d69a6c99 --- /dev/null +++ b/tuskar_ui/infrastructure/resources_management/panel.py @@ -0,0 +1,27 @@ +# -*- 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 _ # noqa + +import horizon + +from tuskar_ui.infrastructure import dashboard + + +class ResourcesManagement(horizon.Panel): + name = _("Management Nodes") + slug = "resources_management" + + +dashboard.Infrastructure.register(ResourcesManagement) diff --git a/tuskar_ui/infrastructure/resources_management/urls.py b/tuskar_ui/infrastructure/resources_management/urls.py new file mode 100644 index 00000000..5ecf4c3a --- /dev/null +++ b/tuskar_ui/infrastructure/resources_management/urls.py @@ -0,0 +1,23 @@ +# -*- 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.resources_management import views + + +urlpatterns = defaults.patterns( + '', + defaults.url(r'^$', views.IndexView.as_view(), name='index'), +) diff --git a/tuskar_ui/infrastructure/resources_management/views.py b/tuskar_ui/infrastructure/resources_management/views.py new file mode 100644 index 00000000..f046b626 --- /dev/null +++ b/tuskar_ui/infrastructure/resources_management/views.py @@ -0,0 +1,18 @@ +# -*- 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' diff --git a/tuskar_ui/infrastructure/resources_overview/__init__.py b/tuskar_ui/infrastructure/resources_overview/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tuskar_ui/infrastructure/resources_overview/__init__.py diff --git a/tuskar_ui/infrastructure/resources_overview/panel.py b/tuskar_ui/infrastructure/resources_overview/panel.py new file mode 100644 index 00000000..746a81b8 --- /dev/null +++ b/tuskar_ui/infrastructure/resources_overview/panel.py @@ -0,0 +1,27 @@ +# -*- 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 _ # noqa + +import horizon + +from tuskar_ui.infrastructure import dashboard + + +class ResourcesOverview(horizon.Panel): + name = _("Overview") + slug = "resources_overview" + + +dashboard.Infrastructure.register(ResourcesOverview) diff --git a/tuskar_ui/infrastructure/resources_overview/urls.py b/tuskar_ui/infrastructure/resources_overview/urls.py new file mode 100644 index 00000000..5638adfc --- /dev/null +++ b/tuskar_ui/infrastructure/resources_overview/urls.py @@ -0,0 +1,23 @@ +# -*- 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.resources_overview import views + + +urlpatterns = defaults.patterns( + '', + defaults.url(r'^$', views.IndexView.as_view(), name='index'), +) diff --git a/tuskar_ui/infrastructure/resources_overview/views.py b/tuskar_ui/infrastructure/resources_overview/views.py new file mode 100644 index 00000000..f046b626 --- /dev/null +++ b/tuskar_ui/infrastructure/resources_overview/views.py @@ -0,0 +1,18 @@ +# -*- 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' diff --git a/tuskar_ui/infrastructure/resources_resource/__init__.py b/tuskar_ui/infrastructure/resources_resource/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tuskar_ui/infrastructure/resources_resource/__init__.py diff --git a/tuskar_ui/infrastructure/service_management/panel.py b/tuskar_ui/infrastructure/resources_resource/panel.py index f6d31b49..54286120 100644 --- a/tuskar_ui/infrastructure/service_management/panel.py +++ b/tuskar_ui/infrastructure/resources_resource/panel.py @@ -16,12 +16,12 @@ from django.utils.translation import ugettext_lazy as _ # noqa import horizon -#from tuskar_ui.infrastructure import dashboard +from tuskar_ui.infrastructure import dashboard -class Service_Management(horizon.Panel): - name = _("Service Management") - slug = "service_management" +class ResourcesResource(horizon.Panel): + name = _("Resource Nodes") + slug = "resources_resource" -#dashboard.Infrastructure.register(Service_Management) +dashboard.Infrastructure.register(ResourcesResource) diff --git a/tuskar_ui/infrastructure/resources_resource/urls.py b/tuskar_ui/infrastructure/resources_resource/urls.py new file mode 100644 index 00000000..b06e8c69 --- /dev/null +++ b/tuskar_ui/infrastructure/resources_resource/urls.py @@ -0,0 +1,23 @@ +# -*- 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.resources_resource import views + + +urlpatterns = defaults.patterns( + '', + defaults.url(r'^$', views.IndexView.as_view(), name='index'), +) diff --git a/tuskar_ui/infrastructure/resources_resource/views.py b/tuskar_ui/infrastructure/resources_resource/views.py new file mode 100644 index 00000000..f046b626 --- /dev/null +++ b/tuskar_ui/infrastructure/resources_resource/views.py @@ -0,0 +1,18 @@ +# -*- 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' diff --git a/tuskar_ui/infrastructure/resources_unallocated/__init__.py b/tuskar_ui/infrastructure/resources_unallocated/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tuskar_ui/infrastructure/resources_unallocated/__init__.py diff --git a/tuskar_ui/infrastructure/resources_unallocated/panel.py b/tuskar_ui/infrastructure/resources_unallocated/panel.py new file mode 100644 index 00000000..b78b679d --- /dev/null +++ b/tuskar_ui/infrastructure/resources_unallocated/panel.py @@ -0,0 +1,27 @@ +# -*- 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 _ # noqa + +import horizon + +from tuskar_ui.infrastructure import dashboard + + +class ResourcesUnallocated(horizon.Panel): + name = _("Unallocated") + slug = "resources_unallocated" + + +dashboard.Infrastructure.register(ResourcesUnallocated) diff --git a/tuskar_ui/infrastructure/resources_unallocated/urls.py b/tuskar_ui/infrastructure/resources_unallocated/urls.py new file mode 100644 index 00000000..b96f8861 --- /dev/null +++ b/tuskar_ui/infrastructure/resources_unallocated/urls.py @@ -0,0 +1,23 @@ +# -*- 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.resources_unallocated import views + + +urlpatterns = defaults.patterns( + '', + defaults.url(r'^$', views.IndexView.as_view(), name='index'), +) diff --git a/tuskar_ui/infrastructure/resources_unallocated/views.py b/tuskar_ui/infrastructure/resources_unallocated/views.py new file mode 100644 index 00000000..f046b626 --- /dev/null +++ b/tuskar_ui/infrastructure/resources_unallocated/views.py @@ -0,0 +1,18 @@ +# -*- 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' diff --git a/tuskar_ui/infrastructure/service_management/templates/service_management/index.html b/tuskar_ui/infrastructure/service_management/templates/service_management/index.html deleted file mode 100644 index 7de2a028..00000000 --- a/tuskar_ui/infrastructure/service_management/templates/service_management/index.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'infrastructure/base.html' %} -{% load i18n %} -{% block title %}{% trans "Service Management" %}{% endblock %} - -{% block page_header %} - {% include "horizon/common/_page_header.html" with title=_("Service Management") %} -{% endblock page_header %} - -{% block infrastructure_main %} -{% endblock %} - - |