From 8f94593666e7a00a11bda9320636389d39b461ed Mon Sep 17 00:00:00 2001 From: Elizabeth Elwell Date: Thu, 4 Feb 2016 13:32:24 +0000 Subject: [PATCH] Reorganise Python according to Horizon plugin doc Moved Python from ironic_ui/ironic to ironic_ui/content/ironic. Rename API files according to Horizon plugin doc. Co-Authored-By: Peter Piela Change-Id: If3af9eec0b30825eb59fa5d2d4dc7a26446a4faf --- ironic_ui/api/ironic.py | 0 ironic_ui/api/my_rest_api.py | 124 ++++++++++++++++++ ironic_ui/api/myservice.py | 119 +++++++++++++++++ ironic_ui/api/rest/ironic.py | 0 ironic_ui/content/__init__.py | 19 +++ .../{api/rest => content/ironic}/__init__.py | 0 ironic_ui/{ => content}/ironic/panel.py | 0 ironic_ui/{ => content}/ironic/urls.py | 7 +- ironic_ui/{ => content}/ironic/views.py | 11 +- ironic_ui/enabled/_2200_ironic.py | 4 +- ironic_ui/ironic/__init__.py | 0 ironic_ui/test/tests/registration.py | 3 +- setup.py | 4 +- 13 files changed, 282 insertions(+), 9 deletions(-) delete mode 100644 ironic_ui/api/ironic.py create mode 100755 ironic_ui/api/my_rest_api.py create mode 100755 ironic_ui/api/myservice.py delete mode 100644 ironic_ui/api/rest/ironic.py create mode 100644 ironic_ui/content/__init__.py rename ironic_ui/{api/rest => content/ironic}/__init__.py (100%) rename ironic_ui/{ => content}/ironic/panel.py (100%) rename ironic_ui/{ => content}/ironic/urls.py (78%) rename ironic_ui/{ => content}/ironic/views.py (78%) delete mode 100644 ironic_ui/ironic/__init__.py diff --git a/ironic_ui/api/ironic.py b/ironic_ui/api/ironic.py deleted file mode 100644 index e69de29b..00000000 diff --git a/ironic_ui/api/my_rest_api.py b/ironic_ui/api/my_rest_api.py new file mode 100755 index 00000000..3f7afb01 --- /dev/null +++ b/ironic_ui/api/my_rest_api.py @@ -0,0 +1,124 @@ +# +# Copyright 2015, 2016 Hewlett Packard Enterprise Development Company LP +# Copyright 2016 Cray Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.views import generic + +from ironic_ui.api import myservice + +from openstack_dashboard.api.rest import urls + +from openstack_dashboard.api.rest import utils as rest_utils + + +@urls.register +class Nodes(generic.View): + + url_regex = r'ironic/nodes/$' + + @rest_utils.ajax() + def get(self, request): + """Get the list of nodes. + + :param request: HTTP request. + :return: nodes. + """ + items = myservice.node_list(request) + return { + 'items': [i.to_dict() for i in items], + } + + +@urls.register +class Node(generic.View): + + url_regex = r'ironic/nodes/(?P[0-9a-f-]+)$' + + @rest_utils.ajax() + def get(self, request, node_id): + """Get information on a specific node. + + :param request: HTTP request. + :param node_id: Node name or uuid. + :return: node. + """ + return myservice.node_get(request, node_id).to_dict() + + +@urls.register +class Ports(generic.View): + + url_regex = r'ironic/ports/$' + + @rest_utils.ajax() + def get(self, request): + """Get the list of ports associated with a specified node. + + :param request: HTTP request + :return: List of ports. + """ + node_id = request.GET.get('node_id') + items = myservice.node_list_ports(request, node_id) + return { + 'items': [i.to_dict() for i in items], + } + + +@urls.register +class StatesPower(generic.View): + + url_regex = r'ironic/nodes/(?P[0-9a-f-]+)/states/power$' + + @rest_utils.ajax(data_required=True) + def patch(self, request, node_id): + """Set the power state for a specified node. + + :param request: HTTP request. + :param node_id: Node name or uuid + :return: Return code + """ + state = request.DATA.get('state') + return myservice.node_set_power_state(request, node_id, state) + + +@urls.register +class Maintenance(generic.View): + + url_regex = r'ironic/nodes/(?P[0-9a-f-]+)/maintenance$' + + @rest_utils.ajax() + def patch(self, request, node_id): + """Put a specified node into maintetance state + + :param request: HTTP request. + :param node_id: Node name or uuid + :return: Return code + """ + maint_reason = request.DATA.get('maint_reason') + return myservice.node_set_maintenance( + request, + node_id, + 'on', + maint_reason=maint_reason) + + @rest_utils.ajax() + def delete(self, request, node_id): + """Take a specified node out of the maintetance state + + :param request: HTTP request. + :param node_id: Node name or uuid + :return: Return code + """ + return myservice.node_set_maintenance(request, node_id, 'off') diff --git a/ironic_ui/api/myservice.py b/ironic_ui/api/myservice.py new file mode 100755 index 00000000..1e28ce53 --- /dev/null +++ b/ironic_ui/api/myservice.py @@ -0,0 +1,119 @@ +# +# Copyright 2015, 2016 Hewlett Packard Enterprise Development Company LP +# Copyright 2016 Cray Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging + +from django.conf import settings + +from ironicclient import client + +from horizon.utils.memoized import memoized # noqa + +from openstack_dashboard.api import base + + +LOG = logging.getLogger(__name__) + +DEFAULT_IRONIC_API_VERSION = '1.6' +DEFAULT_INSECURE = False +DEFAULT_CACERT = None + +IRONIC_CLIENT_CLASS_NAME = 'baremetal' + + +@memoized +def ironicclient(request): + """Returns a client connected to the Ironic backend. + + :param request: HTTP request. + :return: Ironic client. + """ + insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', DEFAULT_INSECURE) + cacert = getattr(settings, 'OPENSTACK_SSL_CACERT', DEFAULT_CACERT) + ironic_url = base.url_for(request, IRONIC_CLIENT_CLASS_NAME) + + return client.Client(1, + ironic_url, + os_ironic_api_version=DEFAULT_IRONIC_API_VERSION, + project_id=request.user.project_id, + token=request.user.token.id, + insecure=insecure, + cacert=cacert) + + +def node_list(request): + """Retrieve a list of nodes. + + :param request: HTTP request. + :return: A list of nodes. + + http://docs.openstack.org/developer/python-ironicclient/api/ironicclient.v1.node.html#ironicclient.v1.node.NodeManager.list + """ + node_manager = ironicclient(request).node + return node_manager.list(detail=True, limit=0) + + +def node_get(request, node_id): + """Retrieve a node. + + :param request: HTTP request. + :param node_id: The UUID of the node. + :return: node. + + http://docs.openstack.org/developer/python-ironicclient/api/ironicclient.v1.node.html#ironicclient.v1.node.NodeManager.get + """ + return ironicclient(request).node.get(node_id) + + +def node_list_ports(request, node_id): + """List all the ports on a given node. + + :param request: HTTP request. + :param node_id: The UUID of the node. + :return: A full list of ports. (limit=0) + + http://docs.openstack.org/developer/python-ironicclient/api/ironicclient.v1.node.html#ironicclient.v1.node.NodeManager.list_ports + """ + return ironicclient(request).node.list_ports(node_id, limit=0, detail=True) + + +def node_set_power_state(request, node_id, state): + """Set power state for a given node. + + :param request: HTTP request. + :param node_id: The UUID of the node. + :param state: the power state to set. + :return: node. + + http://docs.openstack.org/developer/python-ironicclient/api/ironicclient.v1.node.html#ironicclient.v1.node.NodeManager.set_power_state + """ + return ironicclient(request).node.set_power_state(node_id, state) + + +def node_set_maintenance(request, node_id, state, maint_reason=None): + """Set the maintenance mode on a given node. + + :param request: HTTP request. + :param node_id: The UUID of the node. + :param state: The maintenance state to set. + :return: node. + + http://docs.openstack.org/developer/python-ironicclient/api/ironicclient.v1.node.html#ironicclient.v1.node.NodeManager.set_maintenance + """ + return ironicclient(request).node.set_maintenance( + node_id, + state, + maint_reason=maint_reason) diff --git a/ironic_ui/api/rest/ironic.py b/ironic_ui/api/rest/ironic.py deleted file mode 100644 index e69de29b..00000000 diff --git a/ironic_ui/content/__init__.py b/ironic_ui/content/__init__.py new file mode 100644 index 00000000..7abed690 --- /dev/null +++ b/ironic_ui/content/__init__.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- + +# 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 pbr.version + + +__version__ = pbr.version.VersionInfo( + 'ironic-ui').version_string() diff --git a/ironic_ui/api/rest/__init__.py b/ironic_ui/content/ironic/__init__.py similarity index 100% rename from ironic_ui/api/rest/__init__.py rename to ironic_ui/content/ironic/__init__.py diff --git a/ironic_ui/ironic/panel.py b/ironic_ui/content/ironic/panel.py similarity index 100% rename from ironic_ui/ironic/panel.py rename to ironic_ui/content/ironic/panel.py diff --git a/ironic_ui/ironic/urls.py b/ironic_ui/content/ironic/urls.py similarity index 78% rename from ironic_ui/ironic/urls.py rename to ironic_ui/content/ironic/urls.py index 2b1780d3..9861b343 100644 --- a/ironic_ui/ironic/urls.py +++ b/ironic_ui/content/ironic/urls.py @@ -1,5 +1,6 @@ # Copyright 2016 Cisco Systems, Inc. # Copyright (c) 2016 Hewlett Packard Enterprise Development Company LP +# Copyright (c) 2016 Cray Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,8 +15,10 @@ # limitations under the License. from django.conf.urls import url -from ironic_ui.ironic import views + +from ironic_ui.content.ironic import views urlpatterns = [ - url(r'^$', views.IndexView.as_view(), name="index"), + url(r'^$', views.IndexView.as_view(), name='index'), + url(r'^([^/]+)/$', views.DetailView.as_view(), name='detail'), ] diff --git a/ironic_ui/ironic/views.py b/ironic_ui/content/ironic/views.py similarity index 78% rename from ironic_ui/ironic/views.py rename to ironic_ui/content/ironic/views.py index 7be81712..66e1df31 100644 --- a/ironic_ui/ironic/views.py +++ b/ironic_ui/content/ironic/views.py @@ -1,5 +1,6 @@ # Copyright 2016 Cisco Systems, Inc. # Copyright (c) 2016 Hewlett Packard Enterprise Development Company LP +# Copyright (c) 2016 Cray Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -13,10 +14,12 @@ # License for the specific language governing permissions and limitations # under the License. -from django.utils.translation import ugettext_lazy as _ -from horizon import views +from django.views import generic -class IndexView(views.HorizonTemplateView): +class IndexView(generic.TemplateView): template_name = 'admin/ironic/index.html' - page_title = _("Ironic Bare Metal Provisioning") + + +class DetailView(generic.TemplateView): + template_name = 'admin/ironic/node_detail.html' diff --git a/ironic_ui/enabled/_2200_ironic.py b/ironic_ui/enabled/_2200_ironic.py index 9a655dc2..37ed4386 100644 --- a/ironic_ui/enabled/_2200_ironic.py +++ b/ironic_ui/enabled/_2200_ironic.py @@ -1,4 +1,5 @@ # Copyright (c) 2016 Hewlett Packard Enterprise Development Company LP +# Copyright (c) 2016 Cray Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,8 +21,9 @@ PANEL_DASHBOARD = 'admin' # The name of the panel group the PANEL is associated with. PANEL_GROUP = 'admin' # Python panel class of the PANEL to be added. -ADD_PANEL = 'ironic_ui.ironic.panel.Ironic' +ADD_PANEL = 'ironic_ui.content.ironic.panel.Ironic' # A list of applications to be prepended to INSTALLED_APPS ADD_INSTALLED_APPS = ['ironic_ui', ] +ADD_ANGULAR_MODULES = ['horizon.dashboard.admin.ironic'] # Automatically discover static resources in installed apps AUTO_DISCOVER_STATIC_FILES = True diff --git a/ironic_ui/ironic/__init__.py b/ironic_ui/ironic/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/ironic_ui/test/tests/registration.py b/ironic_ui/test/tests/registration.py index 51510a41..e7a1ebb9 100644 --- a/ironic_ui/test/tests/registration.py +++ b/ironic_ui/test/tests/registration.py @@ -1,4 +1,5 @@ # Copyright 2015 Cisco Systems, Inc. +# Copyright (c) 2016 Hewlett Packard Enterprise Development Company LP # # 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 @@ -13,7 +14,7 @@ # under the License. import horizon -from ironic_ui.ironic.panel import Ironic +from ironic_ui.content.ironic.panel import Ironic from openstack_dashboard.test import helpers as test diff --git a/setup.py b/setup.py index c4f06b70..d5c114c4 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,6 @@ # Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # Copyright (c) 2016 Hewlett Packard Enterprise Development Company LP +# Copyright (c) 2016 Cray Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -26,5 +27,6 @@ except ImportError: pass setuptools.setup( - setup_requires=['pbr>=1.8'], + setup_requires=['pbr>=1.8', + 'python-ironicclient>=1.1'], pbr=True)