Browse Source

Merge "Drop Heat related code from horizon"

Zuul 1 year ago
parent
commit
b4fccffccc
94 changed files with 17 additions and 5977 deletions
  1. 0
    5
      doc/source/admin/manage-services.rst
  2. 0
    1
      doc/source/configuration/customizing.rst
  3. 0
    24
      doc/source/configuration/settings.rst
  4. 1
    1
      doc/source/contributor/quickstart.rst
  5. 0
    3
      doc/source/contributor/ref/local_conf.rst
  6. 0
    1
      doc/source/install/from-source.rst
  7. 0
    1
      doc/source/user/index.rst
  8. 0
    17
      doc/source/user/log-in.rst
  9. 0
    149
      doc/source/user/stacks.rst
  10. 0
    2
      openstack_dashboard/api/__init__.py
  11. 0
    265
      openstack_dashboard/api/heat.py
  12. 0
    2
      openstack_dashboard/api/rest/__init__.py
  13. 0
    51
      openstack_dashboard/api/rest/heat.py
  14. 0
    92
      openstack_dashboard/conf/heat_policy.json
  15. 1
    2
      openstack_dashboard/dashboards/admin/dashboard.py
  16. 1
    2
      openstack_dashboard/dashboards/admin/info/panel.py
  17. 0
    42
      openstack_dashboard/dashboards/admin/info/tables.py
  18. 1
    26
      openstack_dashboard/dashboards/admin/info/tabs.py
  19. 1
    16
      openstack_dashboard/dashboards/admin/info/tests.py
  20. 0
    0
      openstack_dashboard/dashboards/project/stacks/__init__.py
  21. 0
    83
      openstack_dashboard/dashboards/project/stacks/api.py
  22. 0
    488
      openstack_dashboard/dashboards/project/stacks/forms.py
  23. 0
    350
      openstack_dashboard/dashboards/project/stacks/mappings.py
  24. 0
    21
      openstack_dashboard/dashboards/project/stacks/panel.py
  25. 0
    0
      openstack_dashboard/dashboards/project/stacks/resource_types/__init__.py
  26. 0
    23
      openstack_dashboard/dashboards/project/stacks/resource_types/panel.py
  27. 0
    36
      openstack_dashboard/dashboards/project/stacks/resource_types/tables.py
  28. 0
    32
      openstack_dashboard/dashboards/project/stacks/resource_types/tabs.py
  29. 0
    15
      openstack_dashboard/dashboards/project/stacks/resource_types/templates/stacks.resource_types/_details.html
  30. 0
    52
      openstack_dashboard/dashboards/project/stacks/resource_types/tests.py
  31. 0
    22
      openstack_dashboard/dashboards/project/stacks/resource_types/urls.py
  32. 0
    78
      openstack_dashboard/dashboards/project/stacks/resource_types/views.py
  33. 0
    44
      openstack_dashboard/dashboards/project/stacks/sro.py
  34. 0
    413
      openstack_dashboard/dashboards/project/stacks/tables.py
  35. 0
    173
      openstack_dashboard/dashboards/project/stacks/tabs.py
  36. 0
    0
      openstack_dashboard/dashboards/project/stacks/template_versions/__init__.py
  37. 0
    23
      openstack_dashboard/dashboards/project/stacks/template_versions/panel.py
  38. 0
    52
      openstack_dashboard/dashboards/project/stacks/template_versions/tables.py
  39. 0
    51
      openstack_dashboard/dashboards/project/stacks/template_versions/tabs.py
  40. 0
    3
      openstack_dashboard/dashboards/project/stacks/template_versions/templates/stacks.template_versions/_details.html
  41. 0
    7
      openstack_dashboard/dashboards/project/stacks/template_versions/templates/stacks.template_versions/index.html
  42. 0
    79
      openstack_dashboard/dashboards/project/stacks/template_versions/tests.py
  43. 0
    24
      openstack_dashboard/dashboards/project/stacks/template_versions/urls.py
  44. 0
    61
      openstack_dashboard/dashboards/project/stacks/template_versions/views.py
  45. 0
    7
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_change_template.html
  46. 0
    6
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_create.html
  47. 0
    3
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_events.html
  48. 0
    55
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_overview.html
  49. 0
    3
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_resources.html
  50. 0
    9
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_topology.html
  51. 0
    6
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview.html
  52. 0
    58
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview_details.html
  53. 0
    7
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview_template.html
  54. 0
    10
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_resource_info.html
  55. 0
    38
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_resource_overview.html
  56. 0
    7
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_select_template.html
  57. 0
    14
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_info.html
  58. 0
    5
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_template.html
  59. 0
    6
      openstack_dashboard/dashboards/project/stacks/templates/stacks/_update.html
  60. 0
    7
      openstack_dashboard/dashboards/project/stacks/templates/stacks/change_template.html
  61. 0
    7
      openstack_dashboard/dashboards/project/stacks/templates/stacks/create.html
  62. 0
    7
      openstack_dashboard/dashboards/project/stacks/templates/stacks/preview.html
  63. 0
    7
      openstack_dashboard/dashboards/project/stacks/templates/stacks/preview_details.html
  64. 0
    7
      openstack_dashboard/dashboards/project/stacks/templates/stacks/preview_template.html
  65. 0
    7
      openstack_dashboard/dashboards/project/stacks/templates/stacks/select_template.html
  66. 0
    7
      openstack_dashboard/dashboards/project/stacks/templates/stacks/update.html
  67. 0
    1003
      openstack_dashboard/dashboards/project/stacks/tests.py
  68. 0
    38
      openstack_dashboard/dashboards/project/stacks/urls.py
  69. 0
    358
      openstack_dashboard/dashboards/project/stacks/views.py
  70. 0
    8
      openstack_dashboard/enabled/_1610_orchestration_panel_group.py
  71. 0
    9
      openstack_dashboard/enabled/_1620_project_stacks_panel.py
  72. 0
    10
      openstack_dashboard/enabled/_1630_project_resource_types_panel.py
  73. 0
    10
      openstack_dashboard/enabled/_1640_project_template_versions_panel.py
  74. 0
    5
      openstack_dashboard/exceptions.py
  75. 0
    6
      openstack_dashboard/local/local_settings.py.example
  76. 0
    1
      openstack_dashboard/settings.py
  77. 0
    80
      openstack_dashboard/static/app/core/openstack-service-api/heat.service.js
  78. 0
    80
      openstack_dashboard/static/app/core/openstack-service-api/heat.service.spec.js
  79. 0
    69
      openstack_dashboard/test/api_tests/heat_rest_tests.py
  80. 0
    358
      openstack_dashboard/test/api_tests/heat_tests.py
  81. 0
    11
      openstack_dashboard/test/helpers.py
  82. 0
    2
      openstack_dashboard/test/integration_tests/config.py
  83. 0
    2
      openstack_dashboard/test/integration_tests/horizon.conf
  84. 0
    7
      openstack_dashboard/test/integration_tests/pages/navigation.py
  85. 0
    0
      openstack_dashboard/test/integration_tests/pages/project/orchestration/__init__.py
  86. 0
    99
      openstack_dashboard/test/integration_tests/pages/project/orchestration/stackspage.py
  87. 0
    73
      openstack_dashboard/test/integration_tests/tests/test_stacks.py
  88. 0
    4
      openstack_dashboard/test/test_data/exceptions.py
  89. 0
    617
      openstack_dashboard/test/test_data/heat_data.py
  90. 0
    8
      openstack_dashboard/test/test_data/keystone_data.py
  91. 0
    2
      openstack_dashboard/test/test_data/utils.py
  92. 11
    0
      releasenotes/notes/heat-panel-splitout-b609b157aa4bf29b.yaml
  93. 0
    1
      requirements.txt
  94. 1
    1
      tools/gate/integration/devstack_gate_rc

+ 0
- 5
doc/source/admin/manage-services.rst View File

@@ -30,8 +30,3 @@ As an administrative user, you can view information for OpenStack services.
30 30
    * :guilabel:`Network Agents`:
31 31
      Displays the network agents active within the cluster, such as L3 and
32 32
      DHCP agents, and the status of each agent.
33
-
34
-   * :guilabel:`Orchestration Services`:
35
-     Displays information specific to the Orchestration service. Name,
36
-     engine id, host and topic are listed for each service, as well as its
37
-     activation status.

+ 0
- 1
doc/source/configuration/customizing.rst View File

@@ -116,7 +116,6 @@ You can also override existing methods with your own versions::
116 116
 
117 117
     NO = lambda *x: False
118 118
 
119
-    tabs.HeatServiceTab.allowed = NO
120 119
     tables.AssociateIP.allowed = NO
121 120
     tables.SimpleAssociateIP.allowed = NO
122 121
     tables.SimpleDisassociateIP.allowed = NO

+ 0
- 24
doc/source/configuration/settings.rst View File

@@ -804,7 +804,6 @@ Default:
804 804
         'compute': 'nova_policy.json',
805 805
         'volume': 'cinder_policy.json',
806 806
         'image': 'glance_policy.json',
807
-        'orchestration': 'heat_policy.json',
808 807
         'network': 'neutron_policy.json',
809 808
     }
810 809
 
@@ -1125,29 +1124,6 @@ Default:
1125 1124
 Used to customize features related to the image service, such as the list of
1126 1125
 supported image formats.
1127 1126
 
1128
-Heat
1129
-----
1130
-
1131
-OPENSTACK_HEAT_STACK
1132
-~~~~~~~~~~~~~~~~~~~~
1133
-
1134
-.. versionadded:: 9.0.0(Mitaka)
1135
-
1136
-Default:
1137
-
1138
-.. code-block:: python
1139
-
1140
-    {
1141
-        'enable_user_pass': True
1142
-    }
1143
-
1144
-A dictionary of settings to use with heat stacks. Currently, the only setting
1145
-available is "enable_user_pass", which can be used to disable the password
1146
-field while launching the stack. Currently HEAT API needs user password to
1147
-perform all the heat operations because in HEAT API trusts is not enabled by
1148
-default. So, this setting can be set as "False" in-case HEAT uses trusts by
1149
-default otherwise it needs to be set as "True".
1150
-
1151 1127
 Keystone
1152 1128
 --------
1153 1129
 

+ 1
- 1
doc/source/contributor/quickstart.rst View File

@@ -83,7 +83,7 @@ To start the Horizon development server use the command below
83 83
 
84 84
 .. note::
85 85
 
86
-    The default port for runserver is 8000 which is already consumed by
86
+    The default port for runserver is 8000 which might be already consumed by
87 87
     heat-api-cfn in DevStack. If running in DevStack
88 88
     ``tox -e runserver -- localhost:9000`` will start the test server at
89 89
     ``http://localhost:9000``

+ 0
- 3
doc/source/contributor/ref/local_conf.rst View File

@@ -69,9 +69,6 @@ see https://docs.openstack.org/devstack/latest/
69 69
     SWIFT_REPLICAS=1
70 70
     SWIFT_DATA_DIR=$DEST/data/swift
71 71
 
72
-    # Enable Heat
73
-    enable_plugin heat https://git.openstack.org/openstack/heat
74
-
75 72
     # Enable Neutron
76 73
     enable_plugin neutron https://git.openstack.org/openstack/neutron
77 74
 

+ 0
- 1
doc/source/install/from-source.rst View File

@@ -22,7 +22,6 @@ System Requirements
22 22
 
23 23
   * `cinder <https://docs.openstack.org/cinder/latest/>`_: Block Storage
24 24
   * `glance <https://docs.openstack.org/glance/latest/>`_: Image Management
25
-  * `heat <https://docs.openstack.org/heat/latest/>`_: Orchestration
26 25
   * `neutron <https://docs.openstack.org/neutron/latest/>`_: Networking
27 26
   * `nova <https://docs.openstack.org/nova/latest/>`_: Compute
28 27
   * `swift <https://docs.openstack.org/swift/latest/>`_: Object Storage

+ 0
- 1
doc/source/user/index.rst View File

@@ -18,7 +18,6 @@ sizes of server instances.
18 18
    manage-containers.rst
19 19
    manage-volumes.rst
20 20
    manage-shares.rst
21
-   stacks.rst
22 21
    databases.rst
23 22
    manage-lbaasv2.rst
24 23
    browser_support

+ 0
- 17
doc/source/user/log-in.rst View File

@@ -50,11 +50,6 @@ The dashboard is generally installed on the controller node.
50 50
      (:ref:`dashboard-admin-tab`) and :guilabel:`Identity` tab
51 51
      (:ref:`dashboard-identity-tab`) are displayed.
52 52
 
53
-.. note::
54
-
55
-   Some tabs, such as :guilabel:`Orchestration` and :guilabel:`Firewalls`,
56
-   only appear on the dashboard if they are properly configured.
57
-
58 53
 .. _dashboard-project-tab:
59 54
 
60 55
 OpenStack dashboard — Project tab
@@ -143,15 +138,6 @@ Network tab
143 138
 
144 139
   * :guilabel:`Firewall Rules`: Add and manage firewall rules.
145 140
 
146
-Orchestration tab
147
------------------
148
-
149
-* :guilabel:`Stacks`: Use the REST API to orchestrate multiple composite
150
-  cloud applications.
151
-
152
-* :guilabel:`Resource Types`: Show a list of all the supported resource
153
-  types for HOT templates.
154
-
155 141
 Object Store tab
156 142
 ----------------
157 143
 
@@ -234,9 +220,6 @@ System tab
234 220
 
235 221
   * :guilabel:`Network Agents`: View the network agents.
236 222
 
237
-  * :guilabel:`Orchestration Services`: View a list of all Orchestration
238
-    services.
239
-
240 223
 * :guilabel:`Shares`: Use the following tabs to complete these tasks:
241 224
 
242 225
   * :guilabel:`Shares`: View, create, manage, and delete shares.

+ 0
- 149
doc/source/user/stacks.rst View File

@@ -1,149 +0,0 @@
1
-========================
2
-Launch and manage stacks
3
-========================
4
-
5
-OpenStack Orchestration is a service that you can use to
6
-orchestrate multiple composite cloud applications. This
7
-service supports the use of both the Amazon Web Services (AWS)
8
-CloudFormation template format through both a Query API that
9
-is compatible with CloudFormation and the native OpenStack
10
-Heat Orchestration Template (HOT) format through a REST API.
11
-
12
-These flexible template languages enable application
13
-developers to describe and automate the deployment of
14
-infrastructure, services, and applications. The templates
15
-enable creation of most OpenStack resource types, such as
16
-instances, floating IP addresses, volumes, security groups,
17
-and users. Once created, the resources are referred to as
18
-stacks.
19
-
20
-The template languages are described in the `Template Guide
21
-<https://docs.openstack.org/heat/latest/template_guide/>`_.
22
-
23
-Launch a stack
24
-~~~~~~~~~~~~~~
25
-
26
-#. Log in to the dashboard.
27
-#. Select the appropriate project from the drop down menu at the top left.
28
-#. On the :guilabel:`Project` tab, open the :guilabel:`Orchestration` tab and
29
-   click :guilabel:`Stacks` category.
30
-#. Click :guilabel:`Launch Stack`.
31
-#. In the :guilabel:`Select Template` dialog box, specify the
32
-   following values:
33
-
34
-   +---------------------------------------+-------------------------------+
35
-   | :guilabel:`Template Source`           | Choose the source of the      |
36
-   |                                       | template from the list.       |
37
-   +---------------------------------------+-------------------------------+
38
-   | :guilabel:`Template URL/File/Data`    | Depending on the source that  |
39
-   |                                       | you select, enter the URL,    |
40
-   |                                       | browse to the file location,  |
41
-   |                                       | or directly include the       |
42
-   |                                       | template.                     |
43
-   +---------------------------------------+-------------------------------+
44
-   | :guilabel:`Environment Source`        | Choose the source of the      |
45
-   |                                       | environment from the list.    |
46
-   |                                       | The environment files contain |
47
-   |                                       | additional settings for the   |
48
-   |                                       | stack.                        |
49
-   +---------------------------------------+-------------------------------+
50
-   | :guilabel:`Environment File/Data`     | Depending on the source that  |
51
-   |                                       | you select, browse to the     |
52
-   |                                       | file location, directly       |
53
-   |                                       | include the environment       |
54
-   +---------------------------------------+-------------------------------+
55
-
56
-#. Click :guilabel:`Next`.
57
-#. In the :guilabel:`Launch Stack` dialog box, specify the
58
-   following values:
59
-
60
-   +---------------------------------+---------------------------------+
61
-   | :guilabel:`Stack Name`          | Enter a name to identify        |
62
-   |                                 | the stack.                      |
63
-   +---------------------------------+---------------------------------+
64
-   | :guilabel:`Creation Timeout`    | Specify the number of minutes   |
65
-   | :guilabel:`(minutes)`           | that can elapse before the      |
66
-   |                                 | launch of the stack times out.  |
67
-   +---------------------------------+---------------------------------+
68
-   | :guilabel:`Rollback On Failure` | Select this check box if you    |
69
-   |                                 | want the service to roll back   |
70
-   |                                 | changes if the stack fails to   |
71
-   |                                 | launch.                         |
72
-   +---------------------------------+---------------------------------+
73
-   | :guilabel:`Password for user`   | Specify the password that       |
74
-   | :guilabel:`"demo"`              | the default user uses when the  |
75
-   |                                 | stack is created.               |
76
-   +---------------------------------+---------------------------------+
77
-   | :guilabel:`DBUsername`          | Specify the name of the         |
78
-   |                                 | database user.                  |
79
-   +---------------------------------+---------------------------------+
80
-   | :guilabel:`LinuxDistribution`   | Specify the Linux distribution  |
81
-   |                                 | that is used in the stack.      |
82
-   +---------------------------------+---------------------------------+
83
-   | :guilabel:`DBRootPassword`      | Specify the root password for   |
84
-   |                                 | the database.                   |
85
-   +---------------------------------+---------------------------------+
86
-   | :guilabel:`KeyName`             | Specify the name of the key pair|
87
-   |                                 | to use to log in to the stack.  |
88
-   +---------------------------------+---------------------------------+
89
-   | :guilabel:`DBName`              | Specify the name of the         |
90
-   |                                 | database.                       |
91
-   +---------------------------------+---------------------------------+
92
-   | :guilabel:`DBPassword`          | Specify the password of the     |
93
-   |                                 | database.                       |
94
-   +---------------------------------+---------------------------------+
95
-   | :guilabel:`InstanceType`        | Specify the flavor for the      |
96
-   |                                 | instance.                       |
97
-   +---------------------------------+---------------------------------+
98
-
99
-#. Click :guilabel:`Launch` to create a stack. The :guilabel:`Stacks`
100
-   tab shows the stack.
101
-
102
-After the stack is created, click on the stack name to see the
103
-following details:
104
-
105
-Topology
106
-  The topology of the stack.
107
-
108
-Overview
109
-  The parameters and details of the stack.
110
-
111
-Resources
112
-  The resources used by the stack.
113
-
114
-Events
115
-  The events related to the stack.
116
-
117
-Template
118
-  The template for the stack.
119
-
120
-Manage a stack
121
-~~~~~~~~~~~~~~
122
-
123
-#. Log in to the dashboard.
124
-#. Select the appropriate project from the drop down menu at the top left.
125
-#. On the :guilabel:`Project` tab, open the :guilabel:`Orchestration` tab and
126
-   click :guilabel:`Stacks` category.
127
-#. Select the stack that you want to update.
128
-#. Click :guilabel:`Change Stack Template`.
129
-#. In the :guilabel:`Select Template` dialog box, select the
130
-   new template source or environment source.
131
-#. Click :guilabel:`Next`.
132
-
133
-   The :guilabel:`Update Stack Parameters` window appears.
134
-#. Enter new values for any parameters that you want to update.
135
-#. Click :guilabel:`Update`.
136
-
137
-Delete a stack
138
-~~~~~~~~~~~~~~
139
-
140
-When you delete a stack, you cannot undo this action.
141
-
142
-#. Log in to the dashboard.
143
-#. Select the appropriate project from the drop down menu at the top left.
144
-#. On the :guilabel:`Project` tab, open the :guilabel:`Orchestration` tab and
145
-   click :guilabel:`Stacks` category.
146
-#. Select the stack that you want to delete.
147
-#. Click :guilabel:`Delete Stack`.
148
-#. In the confirmation dialog box, click :guilabel:`Delete Stack`
149
-   to confirm the deletion.

+ 0
- 2
openstack_dashboard/api/__init__.py View File

@@ -34,7 +34,6 @@ Keystone/Nova/Glance/Swift et. al.
34 34
 from openstack_dashboard.api import base
35 35
 from openstack_dashboard.api import cinder
36 36
 from openstack_dashboard.api import glance
37
-from openstack_dashboard.api import heat
38 37
 from openstack_dashboard.api import keystone
39 38
 from openstack_dashboard.api import network
40 39
 from openstack_dashboard.api import neutron
@@ -46,7 +45,6 @@ __all__ = [
46 45
     "base",
47 46
     "cinder",
48 47
     "glance",
49
-    "heat",
50 48
     "keystone",
51 49
     "network",
52 50
     "neutron",

+ 0
- 265
openstack_dashboard/api/heat.py View File

@@ -1,265 +0,0 @@
1
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
2
-# not use this file except in compliance with the License. You may obtain
3
-# a copy of the License at
4
-#
5
-#     http://www.apache.org/licenses/LICENSE-2.0
6
-#
7
-# Unless required by applicable law or agreed to in writing, software
8
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
-# License for the specific language governing permissions and limitations
11
-# under the License.
12
-
13
-import contextlib
14
-
15
-from django.conf import settings
16
-from heatclient import client as heat_client
17
-from heatclient.common import template_format
18
-from heatclient.common import template_utils
19
-from heatclient.common import utils as heat_utils
20
-from oslo_serialization import jsonutils
21
-import six
22
-from six.moves.urllib import request
23
-
24
-from horizon import exceptions
25
-from horizon.utils import functions as utils
26
-from horizon.utils.memoized import memoized
27
-from openstack_dashboard.api import base
28
-from openstack_dashboard.contrib.developer.profiler import api as profiler
29
-
30
-
31
-def format_parameters(params):
32
-    parameters = {}
33
-    for count, p in enumerate(params, 1):
34
-        parameters['Parameters.member.%d.ParameterKey' % count] = p
35
-        parameters['Parameters.member.%d.ParameterValue' % count] = params[p]
36
-    return parameters
37
-
38
-
39
-@memoized
40
-def heatclient(request, password=None):
41
-    api_version = "1"
42
-    insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
43
-    cacert = getattr(settings, 'OPENSTACK_SSL_CACERT', None)
44
-    endpoint = base.url_for(request, 'orchestration')
45
-    kwargs = {
46
-        'token': request.user.token.id,
47
-        'insecure': insecure,
48
-        'ca_file': cacert,
49
-        'username': request.user.username,
50
-        'password': password
51
-        # 'timeout': args.timeout,
52
-        # 'ca_file': args.ca_file,
53
-        # 'cert_file': args.cert_file,
54
-        # 'key_file': args.key_file,
55
-    }
56
-    client = heat_client.Client(api_version, endpoint, **kwargs)
57
-    client.format_parameters = format_parameters
58
-    return client
59
-
60
-
61
-@profiler.trace
62
-def stacks_list(request, marker=None, sort_dir='desc', sort_key='created_at',
63
-                paginate=False, filters=None):
64
-    limit = getattr(settings, 'API_RESULT_LIMIT', 1000)
65
-    page_size = utils.get_page_size(request)
66
-
67
-    if paginate:
68
-        request_size = page_size + 1
69
-    else:
70
-        request_size = limit
71
-
72
-    kwargs = {'sort_dir': sort_dir, 'sort_key': sort_key}
73
-    if marker:
74
-        kwargs['marker'] = marker
75
-
76
-    if filters:
77
-        kwargs.update(filters)
78
-        if 'status' in kwargs:
79
-            kwargs['status'] = kwargs['status'].replace(' ', '_').upper()
80
-
81
-    stacks_iter = heatclient(request).stacks.list(limit=request_size,
82
-                                                  **kwargs)
83
-
84
-    has_prev_data = False
85
-    has_more_data = False
86
-    stacks = list(stacks_iter)
87
-
88
-    if paginate:
89
-        if len(stacks) > page_size:
90
-            stacks.pop()
91
-            has_more_data = True
92
-            if marker is not None:
93
-                has_prev_data = True
94
-        elif sort_dir == 'asc' and marker is not None:
95
-            has_more_data = True
96
-        elif marker is not None:
97
-            has_prev_data = True
98
-    return (stacks, has_more_data, has_prev_data)
99
-
100
-
101
-def _ignore_if(key, value):
102
-    if key != 'get_file' and key != 'type':
103
-        return True
104
-    if not isinstance(value, six.string_types):
105
-        return True
106
-    if (key == 'type' and
107
-            not value.endswith(('.yaml', '.template'))):
108
-        return True
109
-    return False
110
-
111
-
112
-@profiler.trace
113
-def get_template_files(template_data=None, template_url=None):
114
-    if template_data:
115
-        tpl = template_data
116
-    elif template_url:
117
-        with contextlib.closing(request.urlopen(template_url)) as u:
118
-            tpl = u.read()
119
-    else:
120
-        return {}, None
121
-    if not tpl:
122
-        return {}, None
123
-    if isinstance(tpl, six.binary_type):
124
-        tpl = tpl.decode('utf-8')
125
-    template = template_format.parse(tpl)
126
-    files = {}
127
-    _get_file_contents(template, files)
128
-    return files, template
129
-
130
-
131
-def _get_file_contents(from_data, files):
132
-    if not isinstance(from_data, (dict, list)):
133
-        return
134
-    if isinstance(from_data, dict):
135
-        recurse_data = from_data.values()
136
-        for key, value in from_data.items():
137
-            if _ignore_if(key, value):
138
-                continue
139
-            if not value.startswith(('http://', 'https://')):
140
-                raise exceptions.GetFileError(value, 'get_file')
141
-            if value not in files:
142
-                file_content = heat_utils.read_url_content(value)
143
-                if template_utils.is_template(file_content):
144
-                    template = get_template_files(template_url=value)[1]
145
-                    file_content = jsonutils.dumps(template)
146
-                files[value] = file_content
147
-    else:
148
-        recurse_data = from_data
149
-    for value in recurse_data:
150
-        _get_file_contents(value, files)
151
-
152
-
153
-@profiler.trace
154
-def stack_delete(request, stack_id):
155
-    return heatclient(request).stacks.delete(stack_id)
156
-
157
-
158
-@profiler.trace
159
-def stack_get(request, stack_id):
160
-    return heatclient(request).stacks.get(stack_id)
161
-
162
-
163
-@profiler.trace
164
-def template_get(request, stack_id):
165
-    return heatclient(request).stacks.template(stack_id)
166
-
167
-
168
-@profiler.trace
169
-def stack_create(request, password=None, **kwargs):
170
-    return heatclient(request, password).stacks.create(**kwargs)
171
-
172
-
173
-@profiler.trace
174
-def stack_preview(request, password=None, **kwargs):
175
-    return heatclient(request, password).stacks.preview(**kwargs)
176
-
177
-
178
-@profiler.trace
179
-def stack_update(request, stack_id, password=None, **kwargs):
180
-    return heatclient(request, password).stacks.update(stack_id, **kwargs)
181
-
182
-
183
-@profiler.trace
184
-def snapshot_create(request, stack_id):
185
-    return heatclient(request).stacks.snapshot(stack_id)
186
-
187
-
188
-@profiler.trace
189
-def snapshot_list(request, stack_id):
190
-    return heatclient(request).stacks.snapshot_list(stack_id)
191
-
192
-
193
-@profiler.trace
194
-def snapshot_show(request, stack_id, snapshot_id):
195
-    return heatclient(request).stacks.snapshot_show(stack_id, snapshot_id)
196
-
197
-
198
-@profiler.trace
199
-def snapshot_delete(request, stack_id, snapshot_id):
200
-    return heatclient(request).stacks.snapshot_delete(stack_id, snapshot_id)
201
-
202
-
203
-@profiler.trace
204
-def events_list(request, stack_name):
205
-    return heatclient(request).events.list(stack_name)
206
-
207
-
208
-@profiler.trace
209
-def resources_list(request, stack_name):
210
-    return heatclient(request).resources.list(stack_name)
211
-
212
-
213
-@profiler.trace
214
-def resource_get(request, stack_id, resource_name):
215
-    return heatclient(request).resources.get(stack_id, resource_name)
216
-
217
-
218
-@profiler.trace
219
-def resource_metadata_get(request, stack_id, resource_name):
220
-    return heatclient(request).resources.metadata(stack_id, resource_name)
221
-
222
-
223
-@profiler.trace
224
-def template_validate(request, **kwargs):
225
-    return heatclient(request).stacks.validate(**kwargs)
226
-
227
-
228
-@profiler.trace
229
-def action_check(request, stack_id):
230
-    return heatclient(request).actions.check(stack_id)
231
-
232
-
233
-@profiler.trace
234
-def action_suspend(request, stack_id):
235
-    return heatclient(request).actions.suspend(stack_id)
236
-
237
-
238
-@profiler.trace
239
-def action_resume(request, stack_id):
240
-    return heatclient(request).actions.resume(stack_id)
241
-
242
-
243
-@profiler.trace
244
-def resource_types_list(request, filters=None):
245
-    return heatclient(request).resource_types.list(filters=filters)
246
-
247
-
248
-@profiler.trace
249
-def resource_type_get(request, resource_type):
250
-    return heatclient(request).resource_types.get(resource_type)
251
-
252
-
253
-@profiler.trace
254
-def service_list(request):
255
-    return heatclient(request).services.list()
256
-
257
-
258
-@profiler.trace
259
-def template_version_list(request):
260
-    return heatclient(request).template_versions.list()
261
-
262
-
263
-@profiler.trace
264
-def template_function_list(request, template_version):
265
-    return heatclient(request).template_versions.get(template_version)

+ 0
- 2
openstack_dashboard/api/rest/__init__.py View File

@@ -24,7 +24,6 @@ in https://wiki.openstack.org/wiki/APIChangeGuidelines.
24 24
 from openstack_dashboard.api.rest import cinder
25 25
 from openstack_dashboard.api.rest import config
26 26
 from openstack_dashboard.api.rest import glance
27
-from openstack_dashboard.api.rest import heat
28 27
 from openstack_dashboard.api.rest import keystone
29 28
 from openstack_dashboard.api.rest import network
30 29
 from openstack_dashboard.api.rest import neutron
@@ -37,7 +36,6 @@ __all__ = [
37 36
     'cinder',
38 37
     'config',
39 38
     'glance',
40
-    'heat',
41 39
     'keystone',
42 40
     'network',
43 41
     'neutron',

+ 0
- 51
openstack_dashboard/api/rest/heat.py View File

@@ -1,51 +0,0 @@
1
-# Licensed under the Apache License, Version 2.0 (the "License");
2
-# you may not use this file except in compliance with the License.
3
-# You may obtain a copy of the License at
4
-#
5
-#    http://www.apache.org/licenses/LICENSE-2.0
6
-#
7
-# Unless required by applicable law or agreed to in writing, software
8
-# distributed under the License is distributed on an "AS IS" BASIS,
9
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
-# See the License for the specific language governing permissions and
11
-# limitations under the License.
12
-"""API for the heat service."""
13
-
14
-from django.views import generic
15
-
16
-from openstack_dashboard import api
17
-from openstack_dashboard.api.rest import urls
18
-from openstack_dashboard.api.rest import utils as rest_utils
19
-
20
-
21
-@urls.register
22
-class Validate(generic.View):
23
-    """API for validating a template"""
24
-    url_regex = r'heat/validate/$'
25
-
26
-    @rest_utils.ajax(data_required=True)
27
-    def post(self, request):
28
-        """Validate a template
29
-
30
-        The following parameters may be passed in the POST
31
-        application/json object. The parameters are:
32
-        request:
33
-
34
-        :param template_url: The template to validate
35
-        """
36
-        return api.heat.template_validate(request, **(request.DATA))
37
-
38
-
39
-@urls.register
40
-class Services(generic.View):
41
-    """API for heat services."""
42
-    url_regex = r'heat/services/$'
43
-
44
-    @rest_utils.ajax()
45
-    def get(self, request):
46
-        """Get a list of heat services."""
47
-        if api.base.is_service_enabled(request, 'orchestration'):
48
-            result = api.heat.service_list(request)
49
-            return {'items': [u.to_dict() for u in result]}
50
-        else:
51
-            raise rest_utils.AjaxError(501, '')

+ 0
- 92
openstack_dashboard/conf/heat_policy.json View File

@@ -1,92 +0,0 @@
1
-{
2
-    "context_is_admin":  "role:admin",
3
-    "deny_stack_user": "not role:heat_stack_user",
4
-    "deny_everybody": "!",
5
-
6
-    "cloudformation:ListStacks": "rule:deny_stack_user",
7
-    "cloudformation:CreateStack": "rule:deny_stack_user",
8
-    "cloudformation:DescribeStacks": "rule:deny_stack_user",
9
-    "cloudformation:DeleteStack": "rule:deny_stack_user",
10
-    "cloudformation:UpdateStack": "rule:deny_stack_user",
11
-    "cloudformation:CancelUpdateStack": "rule:deny_stack_user",
12
-    "cloudformation:DescribeStackEvents": "rule:deny_stack_user",
13
-    "cloudformation:ValidateTemplate": "rule:deny_stack_user",
14
-    "cloudformation:GetTemplate": "rule:deny_stack_user",
15
-    "cloudformation:EstimateTemplateCost": "rule:deny_stack_user",
16
-    "cloudformation:DescribeStackResource": "",
17
-    "cloudformation:DescribeStackResources": "rule:deny_stack_user",
18
-    "cloudformation:ListStackResources": "rule:deny_stack_user",
19
-
20
-    "cloudwatch:DeleteAlarms": "rule:deny_stack_user",
21
-    "cloudwatch:DescribeAlarmHistory": "rule:deny_stack_user",
22
-    "cloudwatch:DescribeAlarms": "rule:deny_stack_user",
23
-    "cloudwatch:DescribeAlarmsForMetric": "rule:deny_stack_user",
24
-    "cloudwatch:DisableAlarmActions": "rule:deny_stack_user",
25
-    "cloudwatch:EnableAlarmActions": "rule:deny_stack_user",
26
-    "cloudwatch:GetMetricStatistics": "rule:deny_stack_user",
27
-    "cloudwatch:ListMetrics": "rule:deny_stack_user",
28
-    "cloudwatch:PutMetricAlarm": "rule:deny_stack_user",
29
-    "cloudwatch:PutMetricData": "",
30
-    "cloudwatch:SetAlarmState": "rule:deny_stack_user",
31
-
32
-    "actions:action": "rule:deny_stack_user",
33
-    "build_info:build_info": "rule:deny_stack_user",
34
-    "events:index": "rule:deny_stack_user",
35
-    "events:show": "rule:deny_stack_user",
36
-    "resource:index": "rule:deny_stack_user",
37
-    "resource:metadata": "",
38
-    "resource:signal": "",
39
-    "resource:mark_unhealthy": "rule:deny_stack_user",
40
-    "resource:show": "rule:deny_stack_user",
41
-    "stacks:abandon": "rule:deny_stack_user",
42
-    "stacks:create": "rule:deny_stack_user",
43
-    "stacks:delete": "rule:deny_stack_user",
44
-    "stacks:detail": "rule:deny_stack_user",
45
-    "stacks:export": "rule:deny_stack_user",
46
-    "stacks:generate_template": "rule:deny_stack_user",
47
-    "stacks:global_index": "rule:deny_everybody",
48
-    "stacks:index": "rule:deny_stack_user",
49
-    "stacks:list_resource_types": "rule:deny_stack_user",
50
-    "stacks:list_template_versions": "rule:deny_stack_user",
51
-    "stacks:list_template_functions": "rule:deny_stack_user",
52
-    "stacks:lookup": "",
53
-    "stacks:preview": "rule:deny_stack_user",
54
-    "stacks:resource_schema": "rule:deny_stack_user",
55
-    "stacks:show": "rule:deny_stack_user",
56
-    "stacks:template": "rule:deny_stack_user",
57
-    "stacks:environment": "rule:deny_stack_user",
58
-    "stacks:update": "rule:deny_stack_user",
59
-    "stacks:update_patch": "rule:deny_stack_user",
60
-    "stacks:preview_update": "rule:deny_stack_user",
61
-    "stacks:preview_update_patch": "rule:deny_stack_user",
62
-    "stacks:validate_template": "rule:deny_stack_user",
63
-    "stacks:snapshot": "rule:deny_stack_user",
64
-    "stacks:show_snapshot": "rule:deny_stack_user",
65
-    "stacks:delete_snapshot": "rule:deny_stack_user",
66
-    "stacks:list_snapshots": "rule:deny_stack_user",
67
-    "stacks:restore_snapshot": "rule:deny_stack_user",
68
-    "stacks:list_outputs": "rule:deny_stack_user",
69
-    "stacks:show_output": "rule:deny_stack_user",
70
-
71
-    "software_configs:global_index": "rule:deny_everybody",
72
-    "software_configs:index": "rule:deny_stack_user",
73
-    "software_configs:create": "rule:deny_stack_user",
74
-    "software_configs:show": "rule:deny_stack_user",
75
-    "software_configs:delete": "rule:deny_stack_user",
76
-    "software_deployments:index": "rule:deny_stack_user",
77
-    "software_deployments:create": "rule:deny_stack_user",
78
-    "software_deployments:show": "rule:deny_stack_user",
79
-    "software_deployments:update": "rule:deny_stack_user",
80
-    "software_deployments:delete": "rule:deny_stack_user",
81
-    "software_deployments:metadata": "",
82
-
83
-    "service:index": "rule:context_is_admin",
84
-
85
-    "resource_types:OS::Nova::Flavor": "rule:context_is_admin",
86
-    "resource_types:OS::Cinder::EncryptedVolumeType": "rule:context_is_admin",
87
-    "resource_types:OS::Cinder::VolumeType": "rule:context_is_admin",
88
-    "resource_types:OS::Manila::ShareType": "rule:context_is_admin",
89
-    "resource_types:OS::Neutron::QoSPolicy": "rule:context_is_admin",
90
-    "resource_types:OS::Neutron::QoSBandwidthLimitRule": "rule:context_is_admin",
91
-    "resource_types:OS::Nova::HostAggregate": "rule:context_is_admin"
92
-}

+ 1
- 2
openstack_dashboard/dashboards/admin/dashboard.py View File

@@ -28,8 +28,7 @@ class Admin(horizon.Dashboard):
28 28
                         ('image', 'context_is_admin'),
29 29
                         ('volume', 'context_is_admin'),
30 30
                         ('compute', 'context_is_admin'),
31
-                        ('network', 'context_is_admin'),
32
-                        ('orchestration', 'context_is_admin'),)
31
+                        ('network', 'context_is_admin'),)
33 32
     else:
34 33
         permissions = (tuple(utils.get_admin_permissions()),)
35 34
 

+ 1
- 2
openstack_dashboard/dashboards/admin/info/panel.py View File

@@ -26,5 +26,4 @@ class Info(horizon.Panel):
26 26
     slug = 'info'
27 27
     policy_rules = (("compute", "context_is_admin"),
28 28
                     ("volume", "context_is_admin"),
29
-                    ("network", "context_is_admin"),
30
-                    ("orchestration", "context_is_admin"),)
29
+                    ("network", "context_is_admin"),)

+ 0
- 42
openstack_dashboard/dashboards/admin/info/tables.py View File

@@ -236,45 +236,3 @@ class NetworkAgentsTable(tables.DataTable):
236 236
         table_actions = (NetworkAgentsFilterAction, )
237 237
         row_actions = (NetworkL3AgentRoutersLinkAction, )
238 238
         multi_select = False
239
-
240
-
241
-class HeatServiceFilterAction(tables.FilterAction):
242
-    filter_field = 'type'
243
-
244
-    def filter(self, table, services, filter_string):
245
-        q = filter_string.lower()
246
-
247
-        def comp(service):
248
-            attr = getattr(service, self.filter_field, '')
249
-            if attr is not None and q in attr.lower():
250
-                return True
251
-            return False
252
-
253
-        return filter(comp, services)
254
-
255
-
256
-class HeatServiceTable(tables.DataTable):
257
-    hostname = tables.Column('hostname', verbose_name=_('Hostname'))
258
-    binary = tables.Column("binary", verbose_name=_('Name'))
259
-    engine_id = tables.Column('engine_id', verbose_name=_('Engine Id'))
260
-    host = tables.Column('host', verbose_name=_('Host'))
261
-    topic = tables.Column('topic', verbose_name=_('Topic'))
262
-    # For consistent with other tables in system info, set column name to
263
-    # 'state'
264
-    state = tables.Column('status', verbose_name=_('State'),
265
-                          display_choices=SERVICE_STATE_DISPLAY_CHOICES)
266
-    updated_at = tables.Column('updated_at',
267
-                               verbose_name=pgettext_lazy(
268
-                                   'Time since the last update',
269
-                                   u'Last Updated'),
270
-                               filters=(utils_filters.parse_isotime,
271
-                                        filters.timesince))
272
-
273
-    def get_object_id(self, obj):
274
-        return "%s" % obj.engine_id
275
-
276
-    class Meta(object):
277
-        name = "heat_services"
278
-        verbose_name = _("Orchestration Services")
279
-        table_actions = (HeatServiceFilterAction,)
280
-        multi_select = False

+ 1
- 26
openstack_dashboard/dashboards/admin/info/tabs.py View File

@@ -18,7 +18,6 @@ from horizon import exceptions
18 18
 from horizon import tabs
19 19
 from openstack_dashboard.api import base
20 20
 from openstack_dashboard.api import cinder
21
-from openstack_dashboard.api import heat
22 21
 from openstack_dashboard.api import neutron
23 22
 from openstack_dashboard.api import nova
24 23
 from openstack_dashboard.dashboards.admin.info import constants
@@ -118,32 +117,8 @@ class NetworkAgentsTab(tabs.TableTab):
118 117
         return agents
119 118
 
120 119
 
121
-class HeatServiceTab(tabs.TableTab):
122
-    table_classes = (tables.HeatServiceTable,)
123
-    name = tables.HeatServiceTable.Meta.verbose_name
124
-    slug = tables.HeatServiceTable.Meta.name
125
-    template_name = constants.INFO_DETAIL_TEMPLATE_NAME
126
-
127
-    def allowed(self, request):
128
-        try:
129
-            return base.is_service_enabled(request, 'orchestration')
130
-        except Exception:
131
-            exceptions.handle(request, _('Orchestration service is disabled.'))
132
-            return False
133
-
134
-    def get_heat_services_data(self):
135
-        try:
136
-            services = heat.service_list(self.tab_group.request)
137
-        except Exception:
138
-            msg = _('Unable to get Orchestration service list.')
139
-            exceptions.check_message(["Connection", "refused"], msg)
140
-            exceptions.handle(self.request, msg)
141
-            services = []
142
-        return services
143
-
144
-
145 120
 class SystemInfoTabs(tabs.TabGroup):
146 121
     slug = "system_info"
147 122
     tabs = (ServicesTab, NovaServicesTab, CinderServicesTab,
148
-            NetworkAgentsTab, HeatServiceTab)
123
+            NetworkAgentsTab)
149 124
     sticky = True

+ 1
- 16
openstack_dashboard/dashboards/admin/info/tests.py View File

@@ -29,7 +29,7 @@ class SystemInfoViewTests(test.BaseAdminViewTests):
29 29
                         api.nova: ('service_list',),
30 30
                         api.neutron: ('agent_list', 'is_extension_supported'),
31 31
                         api.cinder: ('service_list',),
32
-                        api.heat: ('service_list',)})
32
+                        })
33 33
     def _test_base_index(self):
34 34
         api.base.is_service_enabled(IsA(http.HttpRequest), IgnoreArg()) \
35 35
                 .MultipleTimes().AndReturn(True)
@@ -49,10 +49,6 @@ class SystemInfoViewTests(test.BaseAdminViewTests):
49 49
         api.cinder.service_list(IsA(http.HttpRequest)).\
50 50
             AndReturn(cinder_services)
51 51
 
52
-        heat_services = self.heat_services.list()
53
-        api.heat.service_list(IsA(http.HttpRequest)).\
54
-            AndReturn(heat_services)
55
-
56 52
         self.mox.ReplayAll()
57 53
 
58 54
         res = self.client.get(INDEX_URL)
@@ -88,14 +84,3 @@ class SystemInfoViewTests(test.BaseAdminViewTests):
88 84
         )
89 85
 
90 86
         self.mox.VerifyAll()
91
-
92
-    def test_heat_index(self):
93
-        res = self._test_base_index()
94
-        heat_services_tab = res.context['tab_group'].\
95
-            get_tab('heat_services')
96
-        self.assertQuerysetEqual(
97
-            heat_services_tab._tables['heat_services'].data,
98
-            [service.__repr__() for service in self.heat_services.list()]
99
-        )
100
-
101
-        self.mox.VerifyAll()

+ 0
- 0
openstack_dashboard/dashboards/project/stacks/__init__.py View File


+ 0
- 83
openstack_dashboard/dashboards/project/stacks/api.py View File

@@ -1,83 +0,0 @@
1
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
2
-# not use this file except in compliance with the License. You may obtain
3
-# a copy of the License at
4
-#
5
-#      http://www.apache.org/licenses/LICENSE-2.0
6
-#
7
-# Unless required by applicable law or agreed to in writing, software
8
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
-# License for the specific language governing permissions and limitations
11
-# under the License.
12
-
13
-import json
14
-
15
-from openstack_dashboard.api import heat
16
-
17
-from openstack_dashboard.dashboards.project.stacks import mappings
18
-from openstack_dashboard.dashboards.project.stacks import sro
19
-
20
-
21
-class Stack(object):
22
-    pass
23
-
24
-
25
-def d3_data(request, stack_id=''):
26
-    try:
27
-        stack = heat.stack_get(request, stack_id)
28
-    except Exception:
29
-        stack = Stack()
30
-        stack.id = stack_id
31
-        stack.stack_name = request.session.get('stack_name', '')
32
-        stack.stack_status = 'DELETE_COMPLETE'
33
-        stack.stack_status_reason = 'DELETE_COMPLETE'
34
-
35
-    try:
36
-        resources = heat.resources_list(request, stack.stack_name)
37
-    except Exception:
38
-        resources = []
39
-
40
-    d3_data = {"nodes": [], "stack": {}}
41
-    if stack:
42
-        stack_image = mappings.get_resource_image(stack.stack_status, 'stack')
43
-        stack_node = {
44
-            'stack_id': stack.id,
45
-            'name': stack.stack_name,
46
-            'status': stack.stack_status,
47
-            'image': stack_image,
48
-            'image_size': 60,
49
-            'image_x': -30,
50
-            'image_y': -30,
51
-            'text_x': 40,
52
-            'text_y': ".35em",
53
-            'in_progress': (stack.status == 'IN_PROGRESS'),
54
-            'info_box': sro.stack_info(stack, stack_image)
55
-        }
56
-        d3_data['stack'] = stack_node
57
-
58
-    if resources:
59
-        for resource in resources:
60
-            resource_image = mappings.get_resource_image(
61
-                resource.resource_status,
62
-                resource.resource_type)
63
-            resource_status = mappings.get_resource_status(
64
-                resource.resource_status)
65
-            if resource_status in ('IN_PROGRESS', 'INIT'):
66
-                in_progress = True
67
-            else:
68
-                in_progress = False
69
-            resource_node = {
70
-                'name': resource.resource_name,
71
-                'status': resource.resource_status,
72
-                'image': resource_image,
73
-                'required_by': resource.required_by,
74
-                'image_size': 50,
75
-                'image_x': -25,
76
-                'image_y': -25,
77
-                'text_x': 35,
78
-                'text_y': ".35em",
79
-                'in_progress': in_progress,
80
-                'info_box': sro.resource_info(resource)
81
-            }
82
-            d3_data['nodes'].append(resource_node)
83
-    return json.dumps(d3_data)

+ 0
- 488
openstack_dashboard/dashboards/project/stacks/forms.py View File

@@ -1,488 +0,0 @@
1
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
2
-# not use this file except in compliance with the License. You may obtain
3
-# a copy of the License at
4
-#
5
-#     http://www.apache.org/licenses/LICENSE-2.0
6
-#
7
-# Unless required by applicable law or agreed to in writing, software
8
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
-# License for the specific language governing permissions and limitations
11
-# under the License.
12
-
13
-import json
14
-import logging
15
-
16
-import django
17
-from django.conf import settings
18
-from django.utils import html
19
-from django.utils.translation import ugettext_lazy as _
20
-from django.views.decorators.debug import sensitive_variables
21
-
22
-from oslo_utils import strutils
23
-import six
24
-
25
-from horizon import exceptions
26
-from horizon import forms
27
-from horizon import messages
28
-
29
-from openstack_dashboard import api
30
-from openstack_dashboard.dashboards.project.images \
31
-    import utils as image_utils
32
-from openstack_dashboard.dashboards.project.instances \
33
-    import utils as instance_utils
34
-
35
-
36
-LOG = logging.getLogger(__name__)
37
-
38
-
39
-def create_upload_form_attributes(prefix, input_type, name):
40
-    """Creates attribute dicts for the switchable upload form
41
-
42
-    :type prefix: str
43
-    :param prefix: prefix (environment, template) of field
44
-    :type input_type: str
45
-    :param input_type: field type (file, raw, url)
46
-    :type name: str
47
-    :param name: translated text label to display to user
48
-    :rtype: dict
49
-    :return: an attribute set to pass to form build
50
-    """
51
-    attributes = {'class': 'switched', 'data-switch-on': prefix + 'source'}
52
-    attributes['data-' + prefix + 'source-' + input_type] = name
53
-    return attributes
54
-
55
-
56
-class TemplateForm(forms.SelfHandlingForm):
57
-
58
-    class Meta(object):
59
-        name = _('Select Template')
60
-        help_text = _('Select a template to launch a stack.')
61
-
62
-    # TODO(jomara) - update URL choice for template & environment files
63
-    # w/ client side download when applicable
64
-    base_choices = [('file', _('File')),
65
-                    ('raw', _('Direct Input'))]
66
-    url_choice = [('url', _('URL'))]
67
-    attributes = {'class': 'switchable', 'data-slug': 'templatesource'}
68
-    template_source = forms.ChoiceField(label=_('Template Source'),
69
-                                        choices=base_choices + url_choice,
70
-                                        widget=forms.ThemableSelectWidget(
71
-                                            attrs=attributes))
72
-
73
-    attributes = create_upload_form_attributes(
74
-        'template',
75
-        'file',
76
-        _('Template File'))
77
-    template_upload = forms.FileField(
78
-        label=_('Template File'),
79
-        help_text=_('A local template to upload.'),
80
-        widget=forms.FileInput(attrs=attributes),
81
-        required=False)
82
-
83
-    attributes = create_upload_form_attributes(
84
-        'template',
85
-        'url',
86
-        _('Template URL'))
87
-    template_url = forms.URLField(
88
-        label=_('Template URL'),
89
-        help_text=_('An external (HTTP) URL to load the template from.'),
90
-        widget=forms.TextInput(attrs=attributes),
91
-        required=False)
92
-
93
-    attributes = create_upload_form_attributes(
94
-        'template',
95
-        'raw',
96
-        _('Template Data'))
97
-    template_data = forms.CharField(
98
-        label=_('Template Data'),
99
-        help_text=_('The raw contents of the template.'),
100
-        widget=forms.widgets.Textarea(attrs=attributes),
101
-        required=False)
102
-
103
-    attributes = {'data-slug': 'envsource', 'class': 'switchable'}
104
-    environment_source = forms.ChoiceField(
105
-        label=_('Environment Source'),
106
-        choices=base_choices,
107
-        widget=forms.ThemableSelectWidget(attrs=attributes),
108
-        required=False)
109
-
110
-    attributes = create_upload_form_attributes(
111
-        'env',
112
-        'file',
113
-        _('Environment File'))
114
-    environment_upload = forms.FileField(
115
-        label=_('Environment File'),
116
-        help_text=_('A local environment to upload.'),
117
-        widget=forms.FileInput(attrs=attributes),
118
-        required=False)
119
-
120
-    attributes = create_upload_form_attributes(
121
-        'env',
122
-        'raw',
123
-        _('Environment Data'))
124
-    environment_data = forms.CharField(
125
-        label=_('Environment Data'),
126
-        help_text=_('The raw contents of the environment file.'),
127
-        widget=forms.widgets.Textarea(attrs=attributes),
128
-        required=False)
129
-
130
-    if django.VERSION >= (1, 9):
131
-        # Note(Itxaka): On django>=1.9 Charfield has an strip option that
132
-        # we need to set to False as to not hit
133
-        # https://bugs.launchpad.net/python-heatclient/+bug/1546166
134
-        environment_data.strip = False
135
-        template_data.strip = False
136
-
137
-    def __init__(self, *args, **kwargs):
138
-        self.next_view = kwargs.pop('next_view')
139
-        super(TemplateForm, self).__init__(*args, **kwargs)
140
-
141
-    def clean(self):
142
-        cleaned = super(TemplateForm, self).clean()
143
-
144
-        files = self.request.FILES
145
-        self.clean_uploaded_files('template', _('template'), cleaned, files)
146
-        self.clean_uploaded_files('environment', _('environment'), cleaned,
147
-                                  files)
148
-
149
-        # Validate the template and get back the params.
150
-        kwargs = {}
151
-        if cleaned['environment_data']:
152
-            kwargs['environment'] = cleaned['environment_data']
153
-        try:
154
-            files, tpl =\
155
-                api.heat.get_template_files(cleaned.get('template_data'),
156
-                                            cleaned.get('template_url'))
157
-            kwargs['files'] = files
158
-            kwargs['template'] = tpl
159
-            validated = api.heat.template_validate(self.request, **kwargs)
160
-            cleaned['template_validate'] = validated
161
-            cleaned['template_validate']['files'] = files
162
-            cleaned['template_validate']['template'] = tpl
163
-        except Exception as e:
164
-            raise forms.ValidationError(six.text_type(e))
165
-
166
-        return cleaned
167
-
168
-    def clean_uploaded_files(self, prefix, field_label, cleaned, files):
169
-        """Cleans Template & Environment data from form upload.
170
-
171
-        Does some of the crunchy bits for processing uploads vs raw
172
-        data depending on what the user specified. Identical process
173
-        for environment data & template data.
174
-
175
-        :type prefix: str
176
-        :param prefix: prefix (environment, template) of field
177
-        :type field_label: str
178
-        :param field_label: translated prefix str for messages
179
-        :type input_type: dict
180
-        :param prefix: existing cleaned fields from form
181
-        :rtype: dict
182
-        :return: cleaned dict including environment & template data
183
-        """
184
-
185
-        upload_str = prefix + "_upload"
186
-        data_str = prefix + "_data"
187
-        url = cleaned.get(prefix + '_url')
188
-        data = cleaned.get(prefix + '_data')
189
-
190
-        has_upload = upload_str in files
191
-        # Uploaded file handler
192
-        if has_upload and not url:
193
-            log_template_name = files[upload_str].name
194
-            LOG.info('got upload %s', log_template_name)
195
-
196
-            tpl = files[upload_str].read()
197
-            if tpl.startswith('{'):
198
-                try:
199
-                    json.loads(tpl)
200
-                except Exception as e:
201
-                    msg = _('There was a problem parsing the'
202
-                            ' %(prefix)s: %(error)s')
203
-                    msg = msg % {'prefix': prefix, 'error': six.text_type(e)}
204
-                    raise forms.ValidationError(msg)
205
-            cleaned[data_str] = tpl
206
-
207
-        # URL handler
208
-        elif url and (has_upload or data):
209
-            msg = _('Please specify a %s using only one source method.')
210
-            msg = msg % field_label
211
-            raise forms.ValidationError(msg)
212
-
213
-        elif prefix == 'template':
214
-            # Check for raw template input - blank environment allowed
215
-            if not url and not data:
216
-                msg = _('You must specify a template via one of the '
217
-                        'available sources.')
218
-                raise forms.ValidationError(msg)
219
-
220
-    def create_kwargs(self, data):
221
-        kwargs = {'parameters': data['template_validate'],
222
-                  'environment_data': data['environment_data']}
223
-        if data.get('stack_id'):
224
-            kwargs['stack_id'] = data['stack_id']
225
-        return kwargs
226
-
227
-    def handle(self, request, data):
228
-        kwargs = self.create_kwargs(data)
229
-        # NOTE (gabriel): This is a bit of a hack, essentially rewriting this
230
-        # request so that we can chain it as an input to the next view...
231
-        # but hey, it totally works.
232
-        request.method = 'GET'
233
-
234
-        return self.next_view.as_view()(request, **kwargs)
235
-
236
-
237
-class ChangeTemplateForm(TemplateForm):
238
-    class Meta(object):
239
-        name = _('Edit Template')
240
-        help_text = _('Select a new template to re-launch a stack.')
241
-    stack_id = forms.CharField(label=_('Stack ID'),
242
-                               widget=forms.widgets.HiddenInput)
243
-    stack_name = forms.CharField(label=_('Stack Name'),
244
-                                 widget=forms.TextInput(attrs={'readonly':
245
-                                                               'readonly'}))
246
-
247
-
248
-class PreviewTemplateForm(TemplateForm):
249
-    class Meta(object):
250
-        name = _('Preview Template')
251
-        help_text = _('Select a new template to preview a stack.')
252
-
253
-
254
-class CreateStackForm(forms.SelfHandlingForm):
255
-
256
-    param_prefix = '__param_'
257
-
258
-    class Meta(object):
259
-        name = _('Create Stack')
260
-
261
-    environment_data = forms.CharField(
262
-        widget=forms.widgets.HiddenInput,
263
-        required=False)
264
-    if django.VERSION >= (1, 9):
265
-        # Note(Itxaka): On django>=1.9 Charfield has an strip option that
266
-        # we need to set to False as to not hit
267
-        # https://bugs.launchpad.net/python-heatclient/+bug/1546166
268
-        environment_data.strip = False
269
-
270
-    parameters = forms.CharField(
271
-        widget=forms.widgets.HiddenInput)
272
-    stack_name = forms.RegexField(
273
-        max_length=255,
274
-        label=_('Stack Name'),
275
-        help_text=_('Name of the stack to create.'),
276
-        regex=r"^[a-zA-Z][a-zA-Z0-9_.-]*$",
277
-        error_messages={'invalid':
278
-                        _('Name must start with a letter and may '
279
-                          'only contain letters, numbers, underscores, '
280
-                          'periods and hyphens.')})
281
-    timeout_mins = forms.IntegerField(
282
-        initial=60,
283
-        label=_('Creation Timeout (minutes)'),
284
-        help_text=_('Stack creation timeout in minutes.'))
285
-    enable_rollback = forms.BooleanField(
286
-        label=_('Rollback On Failure'),
287
-        help_text=_('Enable rollback on create/update failure.'),
288
-        required=False)
289
-
290
-    def __init__(self, *args, **kwargs):
291
-        parameters = kwargs.pop('parameters')
292
-        # special case: load template data from API, not passed in params
293
-        if kwargs.get('validate_me'):
294
-            parameters = kwargs.pop('validate_me')
295
-        super(CreateStackForm, self).__init__(*args, **kwargs)
296
-
297
-        if self._stack_password_enabled():
298
-            self.fields['password'] = forms.CharField(
299
-                label=_('Password for user "%s"') % self.request.user.username,
300
-                help_text=_('This is required for operations to be performed '
301
-                            'throughout the lifecycle of the stack'),
302
-                widget=forms.PasswordInput())
303
-
304
-        self._build_parameter_fields(parameters)
305
-
306
-    def _stack_password_enabled(self):
307
-        stack_settings = getattr(settings, 'OPENSTACK_HEAT_STACK', {})
308
-        return stack_settings.get('enable_user_pass', True)
309
-
310
-    def _build_parameter_fields(self, template_validate):
311
-        self.help_text = template_validate['Description']
312
-
313
-        params = template_validate.get('Parameters', {})
314
-        if template_validate.get('ParameterGroups'):
315
-            params_in_order = []
316
-            for group in template_validate['ParameterGroups']:
317
-                for param in group.get('parameters', []):
318
-                    if param in params:
319
-                        params_in_order.append((param, params[param]))
320
-        else:
321
-            # no parameter groups, simply sorted to make the order fixed
322
-            params_in_order = sorted(params.items())
323
-        for param_key, param in params_in_order:
324
-            field = None
325
-            field_key = self.param_prefix + param_key
326
-            initial = param.get('Value',
327
-                                param.get('DefaultValue',
328
-                                          param.get('Default')))
329
-            field_args = {
330
-                'initial': initial,
331
-                'label': param.get('Label', param_key),
332
-                'help_text': html.escape(param.get('Description', '')),
333
-                'required': initial is None,
334
-            }
335
-
336
-            param_type = param.get('Type', None)
337
-            hidden = strutils.bool_from_string(param.get('NoEcho', 'false'))
338
-            if 'CustomConstraint' in param:
339
-                choices = self._populate_custom_choices(
340
-                    param['CustomConstraint'])
341
-                field_args['choices'] = choices
342
-                field = forms.ChoiceField(**field_args)
343
-
344
-            elif 'AllowedValues' in param:
345
-                choices = map(lambda x: (x, x), param['AllowedValues'])
346
-                field_args['choices'] = choices
347
-                field = forms.ChoiceField(**field_args)
348
-
349
-            elif param_type == 'Json' and 'Default' in param:
350
-                field_args['initial'] = json.dumps(param['Default'])
351
-                field = forms.CharField(**field_args)
352
-
353
-            elif param_type in ('CommaDelimitedList', 'String', 'Json'):
354
-                if 'MinLength' in param:
355
-                    field_args['min_length'] = int(param['MinLength'])
356
-                    field_args['required'] = field_args['min_length'] > 0
357
-                if 'MaxLength' in param:
358
-                    field_args['max_length'] = int(param['MaxLength'])
359
-                if hidden:
360
-                    field_args['widget'] = forms.PasswordInput(
361
-                        render_value=True)
362
-                field = forms.CharField(**field_args)
363
-
364
-            elif param_type == 'Number':
365
-                if 'MinValue' in param:
366
-                    field_args['min_value'] = int(param['MinValue'])
367
-                if 'MaxValue' in param:
368
-                    field_args['max_value'] = int(param['MaxValue'])
369
-                field = forms.IntegerField(**field_args)
370
-
371
-            elif param_type == 'Boolean':
372
-                field_args['required'] = False
373
-                field = forms.BooleanField(**field_args)
374
-
375
-            if field:
376
-                self.fields[field_key] = field
377
-
378
-    @sensitive_variables('password')
379
-    def handle(self, request, data):
380
-        prefix_length = len(self.param_prefix)
381
-        params_list = [(k[prefix_length:], v) for (k, v) in data.items()
382
-                       if k.startswith(self.param_prefix)]
383
-        fields = {
384
-            'stack_name': data.get('stack_name'),
385
-            'timeout_mins': data.get('timeout_mins'),
386
-            'disable_rollback': not(data.get('enable_rollback')),
387
-            'parameters': dict(params_list),
388
-            'files': json.loads(data.get('parameters')).get('files'),
389
-            'template': json.loads(data.get('parameters')).get('template')
390
-        }
391
-        if data.get('password'):
392
-            fields['password'] = data.get('password')
393
-
394
-        if data.get('environment_data'):
395
-            fields['environment'] = data.get('environment_data')
396
-
397
-        try:
398
-            api.heat.stack_create(self.request, **fields)
399
-            messages.info(request, _("Stack creation started."))
400
-            return True
401
-        except Exception:
402
-            exceptions.handle(request)
403
-
404
-    def _populate_custom_choices(self, custom_type):
405
-        if custom_type == 'neutron.network':
406
-            return instance_utils.network_field_data(self.request, True)
407
-        if custom_type == 'nova.keypair':
408
-            return instance_utils.keypair_field_data(self.request, True)
409
-        if custom_type == 'glance.image':
410
-            return image_utils.image_field_data(self.request, True)
411
-        if custom_type == 'nova.flavor':
412
-            return instance_utils.flavor_field_data(self.request, True)
413
-        return []
414
-
415
-
416
-class EditStackForm(CreateStackForm):
417
-
418
-    class Meta(object):
419
-        name = _('Update Stack Parameters')
420
-
421
-    stack_id = forms.CharField(
422
-        label=_('Stack ID'),
423
-        widget=forms.widgets.HiddenInput)
424
-    stack_name = forms.CharField(
425
-        label=_('Stack Name'),
426
-        widget=forms.TextInput(attrs={'readonly': 'readonly'}))
427
-
428
-    @sensitive_variables('password')
429
-    def handle(self, request, data):
430
-        prefix_length = len(self.param_prefix)
431
-        params_list = [(k[prefix_length:], v) for (k, v) in data.items()
432
-                       if k.startswith(self.param_prefix)]
433
-
434
-        stack_id = data.get('stack_id')
435
-        fields = {
436
-            'stack_name': data.get('stack_name'),
437
-            'timeout_mins': data.get('timeout_mins'),
438
-            'disable_rollback': not(data.get('enable_rollback')),
439
-            'parameters': dict(params_list),
440
-            'files': json.loads(data.get('parameters')).get('files'),
441
-            'template': json.loads(data.get('parameters')).get('template')
442
-        }
443
-        if data.get('password'):
444
-            fields['password'] = data.get('password')
445
-
446
-        if data.get('environment_data'):
447
-            fields['environment'] = data.get('environment_data')
448
-
449
-        try:
450
-            api.heat.stack_update(self.request, stack_id=stack_id, **fields)
451
-            messages.info(request, _("Stack update started."))
452
-            return True
453
-        except Exception:
454
-            exceptions.handle(request)
455
-
456
-
457
-class PreviewStackForm(CreateStackForm):
458
-
459
-    class Meta(object):
460
-        name = _('Preview Stack Parameters')
461
-
462
-    def __init__(self, *args, **kwargs):
463
-        self.next_view = kwargs.pop('next_view')
464
-        super(CreateStackForm, self).__init__(*args, **kwargs)
465
-
466
-    def handle(self, request, data):
467
-        prefix_length = len(self.param_prefix)
468
-        params_list = [(k[prefix_length:], v) for (k, v) in data.items()
469
-                       if k.startswith(self.param_prefix)]
470
-        fields = {
471
-            'stack_name': data.get('stack_name'),
472
-            'timeout_mins': data.get('timeout_mins'),
473
-            'disable_rollback': not(data.get('enable_rollback')),
474
-            'parameters': dict(params_list),
475
-            'files': json.loads(data.get('parameters')).get('files'),
476
-            'template': json.loads(data.get('parameters')).get('template')
477
-        }
478
-
479
-        if data.get('environment_data'):
480
-            fields['environment'] = data.get('environment_data')
481
-
482
-        try:
483
-            stack_preview = api.heat.stack_preview(self.request, **fields)
484
-            request.method = 'GET'
485
-            return self.next_view.as_view()(request,
486
-                                            stack_preview=stack_preview)
487
-        except Exception:
488
-            exceptions.handle(request)

+ 0
- 350
openstack_dashboard/dashboards/project/stacks/mappings.py View File

@@ -1,350 +0,0 @@
1
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
2
-# not use this file except in compliance with the License. You may obtain
3
-# a copy of the License at
4
-#
5
-#     http://www.apache.org/licenses/LICENSE-2.0
6
-#
7
-# Unless required by applicable law or agreed to in writing, software
8
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
-# License for the specific language governing permissions and limitations
11
-# under the License.
12
-
13
-import json
14
-import logging
15
-
16
-from django.conf import settings
17
-from django.core.urlresolvers import reverse
18
-from django.template.defaultfilters import register
19
-from django.utils import html
20
-from django.utils import safestring
21
-import six
22
-import six.moves.urllib.parse as urlparse
23
-
24
-from openstack_dashboard.api import swift
25
-
26
-LOG = logging.getLogger(__name__)
27
-
28
-
29
-resource_urls = {
30
-    "AWS::AutoScaling::AutoScalingGroup": {
31
-        'link': 'horizon:project:stacks:detail'},
32
-    "AWS::CloudFormation::Stack": {
33
-        'link': 'horizon:project:stacks:detail'},
34
-    "AWS::EC2::Instance": {
35
-        'link': 'horizon:project:instances:detail'},
36
-    "AWS::EC2::InternetGateway": {
37
-        'link': 'horizon:project:networks:ports:detail'},
38
-    "AWS::EC2::NetworkInterface": {
39
-        'link': 'horizon:project:networks:ports:detail'},
40
-    "AWS::EC2::RouteTable": {
41
-        'link': 'horizon:project:routers:detail'},
42
-    "AWS::EC2::SecurityGroup": {
43
-        'link': 'horizon:project:security_groups:index'},
44
-    "AWS::EC2::Subnet": {
45
-        'link': 'horizon:project:networks:subnets:detail'},
46
-    "AWS::EC2::Volume": {
47
-        'link': 'horizon:project:volumes:detail'},
48
-    "AWS::EC2::VPC": {
49
-        'link': 'horizon:project:networks:detail'},
50
-    "AWS::S3::Bucket": {
51
-        'link': 'horizon:project:containers:index'},
52
-    "OS::Cinder::Volume": {
53
-        'link': 'horizon:project:volumes:detail'},
54
-    "OS::Heat::AccessPolicy": {
55
-        'link': 'horizon:project:stacks:detail'},
56
-    "OS::Heat::AutoScalingGroup": {
57
-        'link': 'horizon:project:stacks:detail'},
58
-    "OS::Heat::CloudConfig": {
59
-        'link': 'horizon:project:stacks:detail'},
60
-    "OS::Neutron::Firewall": {
61
-        'link': 'horizon:project:firewalls:firewalldetails'},
62
-    "OS::Neutron::FirewallPolicy": {
63
-        'link': 'horizon:project:firewalls:policydetails'},
64
-    "OS::Neutron::FirewallRule": {
65
-        'link': 'horizon:project:firewalls:ruledetails'},
66
-    "OS::Heat::HARestarter": {
67
-        'link': 'horizon:project:stacks:detail'},
68
-    "OS::Heat::InstanceGroup": {
69
-        'link': 'horizon:project:stacks:detail'},
70
-    "OS::Heat::MultipartMime": {
71
-        'link': 'horizon:project:stacks:detail'},
72
-    "OS::Heat::ResourceGroup": {
73
-        'link': 'horizon:project:stacks:detail'},
74
-    "OS::Heat::SoftwareConfig": {
75
-        'link': 'horizon:project:stacks:detail'},
76
-    "OS::Heat::StructuredConfig": {
77
-        'link': 'horizon:project:stacks:detail'},
78
-    "OS::Heat::StructuredDeployment": {
79
-        'link': 'horizon:project:stacks:detail'},
80
-    "OS::Heat::Stack": {
81
-        'link': 'horizon:project:stacks:detail'},
82
-    "OS::Heat::WaitCondition": {
83
-        'link': 'horizon:project:stacks:detail'},
84
-    "OS::Heat::WaitConditionHandle": {
85
-        'link': 'horizon:project:stacks:detail'},
86
-    "OS::Neutron::IKEPolicy": {
87
-        'link': 'horizon:project:vpn:ikepolicydetails'},
88
-    "OS::Neutron::IPsecPolicy": {
89
-        'link': 'horizon:project:vpn:ipsecpolicydetails'},
90
-    "OS::Neutron::IPsecSiteConnection": {
91
-        'link': 'horizon:project:vpn:ipsecsiteconnectiondetails'},
92
-    "OS::Neutron::Net": {
93
-        'link': 'horizon:project:networks:detail'},
94
-    "OS::Neutron::Port": {
95
-        'link': 'horizon:project:networks:ports:detail'},
96
-    "OS::Neutron::Router": {
97
-        'link': 'horizon:project:routers:detail'},
98
-    "OS::Neutron::Subnet": {
99
-        'link': 'horizon:project:networks:subnets:detail'},
100
-    "OS::Neutron::VPNService": {
101
-        'link': 'horizon:project:vpn:vpnservicedetails'},
102
-    "OS::Nova::KeyPair": {
103
-        'link': 'horizon:project:key_pairs:index'},
104
-    "OS::Nova::Server": {
105
-        'link': 'horizon:project:instances:detail'},
106
-    "OS::Swift::Container": {
107
-        'link': 'horizon:project:containers:index',
108
-        'format_pattern': '%s' + swift.FOLDER_DELIMITER},
109
-}
110
-
111
-
112
-def resource_to_url(resource):
113
-    if (not resource or
114
-            not resource.physical_resource_id or
115
-            not hasattr(resource, 'resource_type')):
116
-        return None
117
-
118
-    mapping = resource_urls.get(resource.resource_type, {})
119
-    try:
120
-        if 'link' not in mapping:
121
-            return None
122
-        format_pattern = mapping.get('format_pattern') or '%s'
123
-        rid = format_pattern % resource.physical_resource_id
124
-        url = reverse(mapping['link'], args=(rid,))
125
-    except Exception as e:
126
-        LOG.exception(e)
127
-        return None
128
-    return url
129
-
130
-
131
-@register.filter
132
-def stack_output(output):
133
-    if not output:
134
-        return u''
135
-    if isinstance(output, six.string_types):
136
-        parts = urlparse.urlsplit(output)
137
-        if parts.netloc and parts.scheme in ('http', 'https'):
138
-            url = html.escape(output)
139
-            safe_link = u'<a href="%s" target="_blank">%s</a>' % (url, url)
140
-            return safestring.mark_safe(safe_link)
141
-    if isinstance(output, dict) or isinstance(output, list):
142
-        output = json.dumps(output, indent=2)
143
-    return safestring.mark_safe(u'<pre>%s</pre>' % html.escape(output))
144
-
145
-static_url = getattr(settings, "STATIC_URL", "/static/")
146
-resource_images = {
147
-    'LB_FAILED': static_url + 'dashboard/img/lb-red.svg',
148
-    'LB_DELETE': static_url + 'dashboard/img/lb-red.svg',
149
-    'LB_IN_PROGRESS': static_url + 'dashboard/img/lb-gray.gif',
150
-    'LB_INIT': static_url + 'dashboard/img/lb-gray.svg',
151
-    'LB_COMPLETE': static_url + 'dashboard/img/lb-green.svg',
152
-    'DB_FAILED': static_url + 'dashboard/img/db-red.svg',
153
-    'DB_DELETE': static_url + 'dashboard/img/db-red.svg',
154
-    'DB_IN_PROGRESS': static_url + 'dashboard/img/db-gray.gif',
155
-    'DB_INIT': static_url + 'dashboard/img/db-gray.svg',
156
-    'DB_COMPLETE': static_url + 'dashboard/img/db-green.svg',
157
-    'STACK_FAILED': static_url + 'dashboard/img/stack-red.svg',
158
-    'STACK_DELETE': static_url + 'dashboard/img/stack-red.svg',
159
-    'STACK_IN_PROGRESS': static_url + 'dashboard/img/stack-gray.gif',
160
-    'STACK_INIT': static_url + 'dashboard/img/stack-gray.svg',
161
-    'STACK_COMPLETE': static_url + 'dashboard/img/stack-green.svg',
162
-    'SERVER_FAILED': static_url + 'dashboard/img/server-red.svg',
163
-    'SERVER_DELETE': static_url + 'dashboard/img/server-red.svg',
164
-    'SERVER_IN_PROGRESS': static_url + 'dashboard/img/server-gray.gif',
165
-    'SERVER_INIT': static_url + 'dashboard/img/server-gray.svg',
166
-    'SERVER_COMPLETE': static_url + 'dashboard/img/server-green.svg',
167
-    'ALARM_FAILED': static_url + 'dashboard/img/alarm-red.svg',
168
-    'ALARM_DELETE': static_url + 'dashboard/img/alarm-red.svg',
169
-    'ALARM_IN_PROGRESS': static_url + 'dashboard/img/alarm-gray.gif',
170
-    'ALARM_INIT': static_url + 'dashboard/img/alarm-gray.svg',
171
-    'ALARM_COMPLETE': static_url + 'dashboard/img/alarm-green.svg',
172
-    'VOLUME_FAILED': static_url + 'dashboard/img/volume-red.svg',
173
-    'VOLUME_DELETE': static_url + 'dashboard/img/volume-red.svg',
174
-    'VOLUME_IN_PROGRESS': static_url + 'dashboard/img/volume-gray.gif',
175
-    'VOLUME_INIT': static_url + 'dashboard/img/volume-gray.svg',
176
-    'VOLUME_COMPLETE': static_url + 'dashboard/img/volume-green.svg',
177
-    'IMAGE_FAILED': static_url + 'dashboard/img/image-red.svg',
178
-    'IMAGE_DELETE': static_url + 'dashboard/img/image-red.svg',
179
-    'IMAGE_IN_PROGRESS': static_url + 'dashboard/img/image-gray.gif',
180
-    'IMAGE_INIT': static_url + 'dashboard/img/image-gray.svg',
181
-    'IMAGE_COMPLETE': static_url + 'dashboard/img/image-green.svg',
182
-    'WAIT_FAILED': static_url + 'dashboard/img/wait-red.svg',
183
-    'WAIT_DELETE': static_url + 'dashboard/img/wait-red.svg',
184
-    'WAIT_IN_PROGRESS': static_url + 'dashboard/img/wait-gray.gif',
185
-    'WAIT_INIT': static_url + 'dashboard/img/wait-gray.svg',
186
-    'WAIT_COMPLETE': static_url + 'dashboard/img/wait-green.svg',
187
-    'FIREWALL_FAILED': static_url + 'dashboard/img/firewall-red.svg',
188
-    'FIREWALL_DELETE': static_url + 'dashboard/img/firewall-red.svg',
189
-    'FIREWALL_IN_PROGRESS': static_url + 'dashboard/img/firewall-gray.gif',
190
-    'FIREWALL_INIT': static_url + 'dashboard/img/firewall-gray.svg',
191
-    'FIREWALL_COMPLETE': static_url + 'dashboard/img/firewall-green.svg',
192
-    'FLOATINGIP_FAILED': static_url + 'dashboard/img/floatingip-red.svg',
193
-    'FLOATINGIP_DELETE': static_url + 'dashboard/img/floatingip-red.svg',
194
-    'FLOATINGIP_IN_PROGRESS': static_url + 'dashboard/img/floatingip-gray.gif',
195
-    'FLOATINGIP_INIT': static_url + 'dashboard/img/floatingip-gray.svg',
196
-    'FLOATINGIP_COMPLETE': static_url + 'dashboard/img/floatingip-green.svg',
197
-    'ROUTER_FAILED': static_url + 'dashboard/img/router-red.svg',
198
-    'ROUTER_DELETE': static_url + 'dashboard/img/router-red.svg',
199
-    'ROUTER_IN_PROGRESS': static_url + 'dashboard/img/router-gray.gif',
200
-    'ROUTER_INIT': static_url + 'dashboard/img/router-gray.svg',
201
-    'ROUTER_COMPLETE': static_url + 'dashboard/img/router-green.svg',
202
-    'POLICY_FAILED': static_url + 'dashboard/img/policy-red.svg',
203
-    'POLICY_DELETE': static_url + 'dashboard/img/policy-red.svg',
204
-    'POLICY_IN_PROGRESS': static_url + 'dashboard/img/policy-gray.gif',
205
-    'POLICY_INIT': static_url + 'dashboard/img/policy-gray.svg',
206
-    'POLICY_COMPLETE': static_url + 'dashboard/img/policy-green.svg',
207
-    'CONFIG_FAILED': static_url + 'dashboard/img/config-red.svg',
208
-    'CONFIG_DELETE': static_url + 'dashboard/img/config-red.svg',
209
-    'CONFIG_IN_PROGRESS': static_url + 'dashboard/img/config-gray.gif',
210
-    'CONFIG_INIT': static_url + 'dashboard/img/config-gray.svg',
211
-    'CONFIG_COMPLETE': static_url + 'dashboard/img/config-green.svg',
212
-    'NETWORK_FAILED': static_url + 'dashboard/img/network-red.svg',
213
-    'NETWORK_DELETE': static_url + 'dashboard/img/network-red.svg',
214
-    'NETWORK_IN_PROGRESS': static_url + 'dashboard/img/network-gray.gif',
215
-    'NETWORK_INIT': static_url + 'dashboard/img/network-gray.svg',
216
-    'NETWORK_COMPLETE': static_url + 'dashboard/img/network-green.svg',
217
-    'PORT_FAILED': static_url + 'dashboard/img/port-red.svg',
218
-    'PORT_DELETE': static_url + 'dashboard/img/port-red.svg',
219
-    'PORT_IN_PROGRESS': static_url + 'dashboard/img/port-gray.gif',
220
-    'PORT_INIT': static_url + 'dashboard/img/port-gray.svg',
221
-    'PORT_COMPLETE': static_url + 'dashboard/img/port-green.svg',
222
-    'SECURITYGROUP_FAILED': static_url + 'dashboard/img/securitygroup-red.svg',
223
-    'SECURITYGROUP_DELETE': static_url + 'dashboard/img/securitygroup-red.svg',
224
-    'SECURITYGROUP_IN_PROGRESS':
225
-        static_url + 'dashboard/img/securitygroup-gray.gif',
226
-    'SECURITYGROUP_INIT': static_url + 'dashboard/img/securitygroup-gray.svg',
227
-    'SECURITYGROUP_COMPLETE':
228
-        static_url + 'dashboard/img/securitygroup-green.svg',
229
-    'VPN_FAILED': static_url + 'dashboard/img/vpn-red.svg',
230
-    'VPN_DELETE': static_url + 'dashboard/img/vpn-red.svg',
231
-    'VPN_IN_PROGRESS': static_url + 'dashboard/img/vpn-gray.gif',
232
-    'VPN_INIT': static_url + 'dashboard/img/vpn-gray.svg',
233
-    'VPN_COMPLETE': static_url + 'dashboard/img/vpn-green.svg',
234
-    'FLAVOR_FAILED': static_url + 'dashboard/img/flavor-red.svg',
235
-    'FLAVOR_DELETE': static_url + 'dashboard/img/flavor-red.svg',
236
-    'FLAVOR_IN_PROGRESS': static_url + 'dashboard/img/flavor-gray.gif',
237
-    'FLAVOR_INIT': static_url + 'dashboard/img/flavor-gray.svg',
238
-    'FLAVOR_COMPLETE': static_url + 'dashboard/img/flavor-green.svg',
239
-    'KEYPAIR_FAILED': static_url + 'dashboard/img/keypair-red.svg',
240
-    'KEYPAIR_DELETE': static_url + 'dashboard/img/keypair-red.svg',
241
-    'KEYPAIR_IN_PROGRESS': static_url + 'dashboard/img/keypair-gray.gif',
242
-    'KEYPAIR_INIT': static_url + 'dashboard/img/keypair-gray.svg',
243
-    'KEYPAIR_COMPLETE': static_url + 'dashboard/img/keypair-green.svg',
244
-    'UNKNOWN_FAILED': static_url + 'dashboard/img/unknown-red.svg',
245
-    'UNKNOWN_DELETE': static_url + 'dashboard/img/unknown-red.svg',
246
-    'UNKNOWN_IN_PROGRESS': static_url + 'dashboard/img/unknown-gray.gif',
247
-    'UNKNOWN_INIT': static_url + 'dashboard/img/unknown-gray.svg',
248
-    'UNKNOWN_COMPLETE': static_url + 'dashboard/img/unknown-green.svg',
249
-}
250
-
251
-
252
-resource_types = {
253
-    # LB
254
-    'LoadBalance': 'LB',
255
-    'HealthMonitor': 'LB',
256
-    'PoolMember': 'LB',
257
-    'Pool': 'LB',
258
-    # DB
259
-    'DBInstance': 'DB',
260
-    'Database': 'DB',
261
-    # SERVER
262
-    'Instance': 'SERVER',
263
-    'Server': 'SERVER',
264
-    # ALARM
265
-    'Alarm': 'ALARM',
266
-    'CombinationAlarm': 'ALARM',
267
-    'CWLiteAlarm': 'ALARM',
268
-    # VOLUME
269
-    'Volume': 'VOLUME',
270
-    'VolumeAttachment': 'VOLUME',
271
-    # STACK
272
-    'stack': 'STACK',
273
-    'AutoScalingGroup': 'STACK',
274
-    'InstanceGroup': 'STACK',
275
-    'ServerGroup': 'STACK',
276
-    'ResourceGroup': 'STACK',
277
-    # IMAGE
278
-    'Image': 'IMAGE',
279
-    # WAIT
280
-    'WaitCondition': 'WAIT',
281
-    'WaitConditionHandle': 'WAIT',
282
-    'UpdateWaitConditionHandle': 'WAIT',
283
-    # FIREWALL
284
-    'Firewall': 'FIREWALL',
285
-    'FirewallPolicy': 'FIREWALL',
286
-    'FirewallRule': 'FIREWALL',
287
-    # FLOATINGIP
288
-    'FloatingIP': 'FLOATINGIP',
289
-    'FloatingIPAssociation': 'FLOATINGIP',
290
-    # ROUTER
291
-    'Router': 'ROUTER',
292
-    'RouterGateway': 'ROUTER',
293
-    'RouterInterface': 'ROUTER',
294
-    # POLICY
295
-    'ScalingPolicy': 'POLICY',
296
-    # CONFIG
297
-    'CloudConfig': 'CONFIG',
298
-    'MultipartMime': 'CONFIG',
299
-    'SoftwareConfig': 'CONFIG',
300
-    'SoftwareDeployment': 'CONFIG',
301
-    'StructuredConfig': 'CONFIG',
302
-    'StructuredDeployment': 'CONFIG',
303
-    # NETWORK
304
-    'Net': 'NETWORK',
305
-    'Subnet': 'NETWORK',
306
-    'NetworkGateway': 'NETWORK',
307
-    'ProviderNet': 'NETWORK',
308
-    # PORT
309
-    'Port': 'PORT',
310
-    # SECURITYGROUP
311
-    'SecurityGroup': 'SECURITYGROUP',
312
-    # VPN
313
-    'VPNService': 'VPN',
314
-    # FLAVOR
315
-    'Flavor': 'FLAVOR',
316
-    # KEYPAIR
317
-    'KeyPair': 'KEYPAIR',
318
-}
319
-
320
-
321
-def get_resource_type(type):
322
-    for key, value in resource_types.items():
323
-        if key in type:
324
-            return value
325
-
326
-    return 'UNKNOWN'
327
-
328
-
329
-def get_resource_status(status):
330
-    if ('IN_PROGRESS' in status):
331
-        return 'IN_PROGRESS'
332
-    elif ('FAILED' in status):
333
-        return 'FAILED'
334
-    elif ('DELETE' in status):
335
-        return 'DELETE'
336
-    elif ('INIT' in status):
337
-        return 'INIT'
338
-    else:
339
-        return 'COMPLETE'
340
-
341
-
342
-def get_resource_image(status, type):
343
-    """Sets the image url and in_progress action sw based on status."""
344
-    resource_type = get_resource_type(type)
345
-    resource_status = get_resource_status(status)
346
-    resource_state = resource_type + "_" + resource_status
347
-
348
-    for key in resource_images:
349
-        if key == resource_state:
350
-            return resource_images.get(key)

+ 0
- 21
openstack_dashboard/dashboards/project/stacks/panel.py View File

@@ -1,21 +0,0 @@
1
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
2
-# not use this file except in compliance with the License. You may obtain
3
-# a copy of the License at
4
-#
5
-#     http://www.apache.org/licenses/LICENSE-2.0
6
-#
7
-# Unless required by applicable law or agreed to in writing, software
8
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
-# License for the specific language governing permissions and limitations
11
-# under the License.
12
-
13
-from django.utils.translation import ugettext_lazy as _
14
-
15
-import horizon
16
-
17
-
18
-class Stacks(horizon.Panel):
19
-    name = _("Stacks")
20
-    slug = "stacks"
21
-    permissions = ('openstack.services.orchestration',)

+ 0
- 0
openstack_dashboard/dashboards/project/stacks/resource_types/__init__.py View File


+ 0
- 23
openstack_dashboard/dashboards/project/stacks/resource_types/panel.py View File

@@ -1,23 +0,0 @@
1
-# Licensed under the Apache License, Version 2.0 (the "License");
2
-# you may not use this file except in compliance with the License.
3
-# You may obtain a copy of the License at
4
-#
5
-#    http://www.apache.org/licenses/LICENSE-2.0
6
-#
7
-# Unless required by applicable law or agreed to in writing, software
8
-# distributed under the License is distributed on an "AS IS" BASIS,
9
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10
-# implied.
11
-# See the License for the specific language governing permissions and
12
-# limitations under the License.
13
-
14
-from django.utils.translation import ugettext_lazy as _
15
-
16
-import horizon
17
-
18
-
19
-class ResourceTypes(horizon.Panel):
20
-    name = _("Resource Types")
21
-    slug = "stacks.resource_types"
22
-    permissions = ('openstack.services.orchestration',)
23
-    policy_rules = (("orchestration", "stacks:list_resource_types"),)

+ 0
- 36
openstack_dashboard/dashboards/project/stacks/resource_types/tables.py View File

@@ -1,36 +0,0 @@
1
-# Licensed under the Apache License, Version 2.0 (the "License");
2
-# you may not use this file except in compliance with the License.
3
-# You may obtain a copy of the License at
4
-#
5
-#    http://www.apache.org/licenses/LICENSE-2.0
6
-#
7
-# Unless required by applicable law or agreed to in writing, software
8
-# distributed under the License is distributed on an "AS IS" BASIS,
9
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10
-# implied.
11
-# See the License for the specific language governing permissions and
12
-# limitations under the License.
13
-
14
-from django.utils.translation import ugettext_lazy as _
15
-
16
-from horizon import tables
17
-
18
-
19
-class ResourceTypesFilterAction(tables.FilterAction):
20
-    filter_type = 'server'
21
-    filter_choices = (('name', _('Type ='), True, _("Case sensitive")),)
22
-
23
-
24
-class ResourceTypesTable(tables.DataTable):
25
-    name = tables.Column("resource_type",
26
-                         verbose_name=_("Type"),
27
-                         link="horizon:project:stacks.resource_types:details",)
28
-
29
-    def get_object_id(self, resource):
30
-        return resource.resource_type
31
-
32
-    class Meta(object):
33
-        name = "resource_types"
34
-        verbose_name = _("Resource Types")
35
-        table_actions = (ResourceTypesFilterAction,)
36
-        multi_select = False

+ 0
- 32
openstack_dashboard/dashboards/project/stacks/resource_types/tabs.py View File

@@ -1,32 +0,0 @@
1
-# Licensed under the Apache License, Version 2.0 (the "License");
2
-# you may not use this file except in compliance with the License.
3
-# You may obtain a copy of the License at
4
-#
5
-#    http://www.apache.org/licenses/LICENSE-2.0
6
-#
7
-# Unless required by applicable law or agreed to in writing, software
8
-# distributed under the License is distributed on an "AS IS" BASIS,
9
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10
-# implied.
11
-# See the License for the specific language governing permissions and
12
-# limitations under the License.
13
-
14
-from django.utils.translation import ugettext_lazy as _
15
-
16
-from horizon import tabs
17
-
18
-
19
-class ResourceTypeOverviewTab(tabs.Tab):
20
-    name = _("Overview")
21
-    slug = "resource_type_overview"
22
-    template_name = "project/stacks.resource_types/_details.html"
23
-
24
-    def get_context_data(self, request):
25
-        return {"r_type": self.tab_group.kwargs['rt'],
26
-                "r_type_attributes": self.tab_group.kwargs['rt_attributes'],
27
-                "r_type_properties": self.tab_group.kwargs['rt_properties']}
28
-
29
-
30
-class ResourceTypeDetailsTabs(tabs.TabGroup):
31
-    slug = "resource_type_details"
32
-    tabs = (ResourceTypeOverviewTab,)

+ 0
- 15
openstack_dashboard/dashboards/project/stacks/resource_types/templates/stacks.resource_types/_details.html View File

@@ -1,15 +0,0 @@
1
-{% load i18n %}
2
-
3
-<div class="detail">
4
-  <dl>
5
-    <dd>{{ r_type }}</dd>
6
-  </dl>
7
-
8
-  <h4>{% trans "Attributes" %}</h4>
9
-  <pre>{{ r_type_attributes }}
10
-  </pre>
11
-
12
-  <h4>{% trans "Properties" %}</h4>
13
-  <pre>{{ r_type_properties }}
14
-  </pre>
15
-</div>

+ 0
- 52
openstack_dashboard/dashboards/project/stacks/resource_types/tests.py View File

@@ -1,52 +0,0 @@
1
-# Licensed under the Apache License, Version 2.0 (the "License");
2
-# you may not use this file except in compliance with the License.
3
-# You may obtain a copy of the License at
4
-#
5
-#    http://www.apache.org/licenses/LICENSE-2.0
6
-#
7
-# Unless required by applicable law or agreed to in writing, software
8
-# distributed under the License is distributed on an "AS IS" BASIS,
9
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10
-# implied.
11
-# See the License for the specific language governing permissions and
12
-# limitations under the License.
13
-
14
-from django.core.urlresolvers import reverse
15
-from django import http
16
-
17
-from mox3.mox import IsA
18
-
19
-from openstack_dashboard import api
20
-from openstack_dashboard.test import helpers as test
21
-
22
-
23
-class ResourceTypesTests(test.TestCase):
24
-
25
-    @test.create_stubs({api.heat: ('resource_types_list',)})
26
-    def test_index(self):
27
-        filters = {}
28
-        api.heat.resource_types_list(
29
-            IsA(http.HttpRequest), filters=filters).AndReturn(
30
-            self.resource_types.list())
31
-        self.mox.ReplayAll()
32
-
33
-        res = self.client.get(
34
-            reverse('horizon:project:stacks.resource_types:index'))
35
-        self.assertTemplateUsed(
36
-            res, 'horizon/common/_data_table_view.html')
37
-        self.assertContains(res, 'AWS::CloudFormation::Stack')
38
-
39
-    @test.create_stubs({api.heat: ('resource_type_get',)})
40
-    def test_detail_view(self):
41
-        rt = self.api_resource_types.first()
42
-
43
-        api.heat.resource_type_get(
44
-            IsA(http.HttpRequest), rt['resource_type']).AndReturn(rt)
45
-        self.mox.ReplayAll()
46
-
47
-        url = reverse('horizon:project:stacks.resource_types:details',
48
-                      args=[rt['resource_type']])
49
-        res = self.client.get(url)
50
-
51
-        self.assertTemplateUsed(res, 'horizon/common/_detail.html')
52
-        self.assertNoMessages()

+ 0
- 22
openstack_dashboard/dashboards/project/stacks/resource_types/urls.py View File

@@ -1,22 +0,0 @@
1
-# Licensed under the Apache License, Version 2.0 (the "License");
2
-# you may not use this file except in compliance with the License.
3
-# You may obtain a copy of the License at
4
-#
5
-#    http://www.apache.org/licenses/LICENSE-2.0
6
-#
7
-# Unless required by applicable law or agreed to in writing, software
8
-# distributed under the License is distributed on an "AS IS" BASIS,
9
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10
-# implied.
11
-# See the License for the specific language governing permissions and
12
-# limitations under the License.
13
-
14
-from django.conf.urls import url
15
-
16
-from openstack_dashboard.dashboards.project.stacks.resource_types import views
17
-
18
-urlpatterns = [
19
-    url(r'^$', views.ResourceTypesView.as_view(), name='index'),
20
-    url(r'^(?P<resource_type>[^/]+)/$',
21
-        views.DetailView.as_view(), name='details'),
22
-]

+ 0
- 78
openstack_dashboard/dashboards/project/stacks/resource_types/views.py View File

@@ -1,78 +0,0 @@
1
-# Licensed under the Apache License, Version 2.0 (the "License");
2
-# you may not use this file except in compliance with the License.
3
-# You may obtain a copy of the License at
4
-#
5
-#    http://www.apache.org/licenses/LICENSE-2.0
6
-#
7
-# Unless required by applicable law or agreed to in writing, software
8
-# distributed under the License is distributed on an "AS IS" BASIS,
9
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10
-# implied.
11
-# See the License for the specific language governing permissions and
12
-# limitations under the License.
13
-
14
-import yaml
15
-
16
-from django.core.urlresolvers import reverse
17
-from django.utils.translation import ugettext_lazy as _
18
-
19
-from horizon import exceptions
20
-from horizon import tables
21
-from horizon import tabs
22
-
23
-from openstack_dashboard import api
24
-import openstack_dashboard.dashboards.project.stacks.resource_types.tables \
25
-    as project_tables
26
-import openstack_dashboard.dashboards.project.stacks.resource_types.tabs \
27
-    as project_tabs
28
-
29
-
30
-class ResourceTypesView(tables.DataTableView):
31
-    table_class = project_tables.ResourceTypesTable
32
-    page_title = _("Resource Types")
33
-
34
-    def get_data(self):
35
-        try:
36
-            filters = self.get_filters()
37
-            if 'name' in filters:
38
-                filters['name'] = '.*' + filters['name']
39
-            r_types = sorted(api.heat.resource_types_list(self.request,
40
-                                                          filters=filters),
41
-                             key=lambda resource: resource.resource_type)
42
-        except Exception:
43
-            r_types = []
44
-            msg = _('Unable to retrieve stack resource types.')
45
-            exceptions.handle(self.request, msg)
46
-        return r_types
47
-
48
-
49
-class DetailView(tabs.TabView):
50
-    tab_group_class = project_tabs.ResourceTypeDetailsTabs
51
-    template_name = 'horizon/common/_detail.html'
52
-    page_title = "{{ resource_type }}"
53
-
54
-    def get_resource_type(self, request, **kwargs):
55
-        try:
56
-            resource_type_overview = api.heat.resource_type_get(
57
-                request,
58
-                kwargs['resource_type'])
59
-            return resource_type_overview
60
-        except Exception:
61
-            msg = _('Unable to retrieve resource type details.')
62
-            exceptions.handle(request, msg, redirect=self.get_redirect_url())
63
-
64
-    def get_tabs(self, request, **kwargs):
65
-        resource_type_overview = self.get_resource_type(request, **kwargs)
66
-        r_type = resource_type_overview['resource_type']
67
-        r_type_attributes = resource_type_overview['attributes']
68
-        r_type_properties = resource_type_overview['properties']
69
-        return self.tab_group_class(
70
-            request,
71
-            rt=r_type,
72
-            rt_attributes=yaml.safe_dump(r_type_attributes, indent=2),
73
-            rt_properties=yaml.safe_dump(r_type_properties, indent=2),
74
-            **kwargs)
75
-
76
-    @staticmethod
77
-    def get_redirect_url():
78
-        return reverse('horizon:project:stacks.resources:index')

+ 0
- 44
openstack_dashboard/dashboards/project/stacks/sro.py View File

@@ -1,44 +0,0 @@
1
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
2
-# not use this file except in compliance with the License. You may obtain
3
-# a copy of the License at
4
-#
5
-#      http://www.apache.org/licenses/LICENSE-2.0
6
-#
7
-# Unless required by applicable law or agreed to in writing, software
8
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
-# License for the specific language governing permissions and limitations
11
-# under the License.
12
-
13
-from django.template.defaultfilters import title
14
-from django.template.loader import render_to_string
15
-
16
-from horizon.utils import filters
17
-
18
-
19
-def stack_info(stack, stack_image):
20
-    stack.stack_status_desc = title(
21
-        filters.replace_underscores(stack.stack_status))
22
-    if stack.stack_status_reason:
23
-        stack.stack_status_reason = title(
24
-            filters.replace_underscores(stack.stack_status_reason)
25
-        )
26
-    context = {}
27
-    context['stack'] = stack
28
-    context['stack_image'] = stack_image
29
-    return render_to_string('project/stacks/_stack_info.html',
30
-                            context)
31
-
32
-
33
-def resource_info(resource):
34
-    resource.resource_status_desc = title(
35
-        filters.replace_underscores(resource.resource_status)
36
-    )
37
-    if resource.resource_status_reason:
38
-        resource.resource_status_reason = title(
39
-            filters.replace_underscores(resource.resource_status_reason)
40
-        )
41
-    context = {}
42
-    context['resource'] = resource
43
-    return render_to_string('project/stacks/_resource_info.html',
44
-                            context)

+ 0
- 413
openstack_dashboard/dashboards/project/stacks/tables.py View File

@@ -1,413 +0,0 @@
1
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
2
-# not use this file except in compliance with the License. You may obtain
3
-# a copy of the License at
4
-#
5
-#     http://www.apache.org/licenses/LICENSE-2.0
6
-#
7
-# Unless required by applicable law or agreed to in writing, software
8
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
-# License for the specific language governing permissions and limitations
11
-# under the License.
12
-
13
-from django.core import urlresolvers
14
-from django.http import Http404
15
-from django.template.defaultfilters import title
16
-from django.utils.translation import pgettext_lazy
17
-from django.utils.translation import ugettext_lazy as _
18
-from django.utils.translation import ungettext_lazy
19
-from heatclient import exc
20
-
21
-from horizon import exceptions
22
-from horizon import messages
23
-from horizon import tables
24
-from horizon.utils import filters
25
-
26
-from openstack_dashboard import api
27
-from openstack_dashboard.dashboards.project.stacks import mappings
28
-
29
-
30
-class LaunchStack(tables.LinkAction):
31
-    name = "launch"
32
-    verbose_name = _("Launch Stack")
33
-    url = "horizon:project:stacks:select_template"
34
-    classes = ("ajax-modal",)
35
-    icon = "plus"
36
-    policy_rules = (("orchestration", "stacks:validate_template"),
37
-                    ("orchestration", "stacks:create"),)
38
-
39
-
40
-class PreviewStack(tables.LinkAction):
41
-    name = "preview"
42
-    verbose_name = _("Preview Stack")
43
-    url = "horizon:project:stacks:preview_template"
44
-    classes = ("ajax-modal",)
45
-    icon = "eye"
46
-    policy_rules = (("orchestration", "stacks:validate_template"),
47
-                    ("orchestration", "stacks:preview"),)
48
-
49
-
50
-class CheckStack(tables.BatchAction):
51
-    name = "check"
52
-    verbose_name = _("Check Stack")
53
-    policy_rules = (("orchestration", "actions:action"),)
54
-    icon = "check-square"
55
-
56
-    @staticmethod
57
-    def action_present(count):
58
-        return ungettext_lazy(
59
-            u"Check Stack",
60
-            u"Check Stacks",
61
-            count
62
-        )
63
-
64
-    @staticmethod
65
-    def action_past(count):
66
-        return ungettext_lazy(
67
-            u"Checked Stack",
68
-            u"Checked Stacks",
69
-            count
70
-        )
71
-
72
-    def action(self, request, stack_id):
73
-        api.heat.action_check(request, stack_id)
74
-
75
-
76
-class SuspendStack(tables.BatchAction):
77
-    name = "suspend"
78
-    verbose_name = _("Suspend Stack")
79
-    policy_rules = (("orchestration", "actions:action"),)
80
-    icon = "pause"
81
-
82
-    @staticmethod
83
-    def action_present(count):
84
-        return ungettext_lazy(
85
-            u"Suspend Stack",
86
-            u"Suspend Stacks",
87
-            count
88
-        )
89
-
90
-    @staticmethod
91
-    def action_past(count):
92
-        return ungettext_lazy(
93
-            u"Suspended Stack",
94
-            u"Suspended Stacks",
95
-            count
96
-        )
97
-
98
-    def action(self, request, stack_id):
99
-        try:
100
-            api.heat.action_suspend(request, stack_id)
101
-        except Exception:
102
-            msg = _('Failed to suspend stack.')
103
-            exceptions.handle(request, msg)
104
-
105
-
106
-class ResumeStack(tables.BatchAction):
107
-    name = "resume"
108
-    verbose_name = _("Resume Stack")
109
-    policy_rules = (("orchestration", "actions:action"),)
110
-    icon = "play"
111
-
112
-    @staticmethod
113
-    def action_present(count):
114
-        return ungettext_lazy(
115
-            u"Resume Stack",
116
-            u"Resume Stacks",
117
-            count
118
-        )
119
-
120
-    @staticmethod
121
-    def action_past(count):
122
-        return ungettext_lazy(
123
-            u"Resumed Stack",
124
-            u"Resumed Stacks",
125
-            count
126
-        )
127
-
128
-    def action(self, request, stack_id):
129
-        try:
130
-            api.heat.action_resume(request, stack_id)
131
-        except Exception:
132
-            msg = _('Failed to resume stack.')
133
-            exceptions.handle(request, msg)
134
-
135
-
136
-class ChangeStackTemplate(tables.LinkAction):
137
-    name = "edit"
138
-    verbose_name = _("Change Stack Template")
139
-    url = "horizon:project:stacks:change_template"
140
-    classes = ("ajax-modal",)
141
-    icon = "pencil"
142
-
143
-    def get_link_url(self, stack):
144
-        return urlresolvers.reverse(self.url, args=[stack.id])
145
-
146
-
147
-class DeleteStack(tables.DeleteAction):
148
-    @staticmethod
149
-    def action_present(count):
150
-        return ungettext_lazy(
151
-            u"Delete Stack",
152
-            u"Delete Stacks",
153
-            count
154
-        )
155
-
156
-    @staticmethod
157
-    def action_past(count):
158
-        return ungettext_lazy(
159
-            u"Deleted Stack",
160
-            u"Deleted Stacks",
161
-            count
162
-        )
163
-
164
-    policy_rules = (("orchestration", "stacks:delete"),)
165
-
166
-    def delete(self, request, stack_id):
167
-        try:
168
-            api.heat.stack_delete(request, stack_id)
169
-        except Exception:
170
-            msg = _('Failed to delete stack.')
171
-            exceptions.handle(request, msg)
172
-
173
-    def allowed(self, request, stack):
174
-        if stack is not None:
175
-            return stack.stack_status != 'DELETE_COMPLETE'
176
-        return True
177
-
178
-
179
-class StacksUpdateRow(tables.Row):
180
-    ajax = True
181
-
182
-    def can_be_selected(self, datum):
183
-        return datum.stack_status != 'DELETE_COMPLETE'
184
-
185
-    def get_data(self, request, stack_id):
186
-        try:
187
-            stack = api.heat.stack_get(request, stack_id)
188
-            if stack.stack_status == 'DELETE_COMPLETE':
189
-                # returning 404 to the ajax call removes the
190
-                # row from the table on the ui
191
-                raise Http404
192
-            return stack
193
-        except Http404:
194
-            raise
195
-        except Exception as e:
196
-            messages.error(request, e)
197
-            raise
198
-
199
-
200
-class StacksFilterAction(tables.FilterAction):
201
-    filter_type = 'server'
202
-    filter_choices = (('name', _('Stack Name ='), True, _('Case-sensitive')),
203
-                      ('id', _('Stack ID ='), True),
204
-                      ('status', _('Status ='), True))
205
-
206
-
207
-class StacksTable(tables.DataTable):
208
-    STATUS_CHOICES = (
209
-        ("Complete", True),
210
-        ("Failed", False),
211
-    )
212
-    STACK_STATUS_DISPLAY_CHOICES = (
213
-        ("init_in_progress", pgettext_lazy("current status of stack",
214
-                                           u"Init In Progress")),
215
-        ("init_complete", pgettext_lazy("current status of stack",
216
-                                        u"Init Complete")),
217
-        ("init_failed", pgettext_lazy("current status of stack",
218
-                                      u"Init Failed")),
219