diff --git a/doc/source/admin/manage-services.rst b/doc/source/admin/manage-services.rst
index 7afaae7f9d..d611911210 100644
--- a/doc/source/admin/manage-services.rst
+++ b/doc/source/admin/manage-services.rst
@@ -30,8 +30,3 @@ As an administrative user, you can view information for OpenStack services.
* :guilabel:`Network Agents`:
Displays the network agents active within the cluster, such as L3 and
DHCP agents, and the status of each agent.
-
- * :guilabel:`Orchestration Services`:
- Displays information specific to the Orchestration service. Name,
- engine id, host and topic are listed for each service, as well as its
- activation status.
diff --git a/doc/source/configuration/customizing.rst b/doc/source/configuration/customizing.rst
index 89ff91624e..bff71f3866 100644
--- a/doc/source/configuration/customizing.rst
+++ b/doc/source/configuration/customizing.rst
@@ -116,7 +116,6 @@ You can also override existing methods with your own versions::
NO = lambda *x: False
- tabs.HeatServiceTab.allowed = NO
tables.AssociateIP.allowed = NO
tables.SimpleAssociateIP.allowed = NO
tables.SimpleDisassociateIP.allowed = NO
diff --git a/doc/source/configuration/settings.rst b/doc/source/configuration/settings.rst
index 7ef538f3df..b8de5bbaba 100644
--- a/doc/source/configuration/settings.rst
+++ b/doc/source/configuration/settings.rst
@@ -782,7 +782,6 @@ Default:
'compute': 'nova_policy.json',
'volume': 'cinder_policy.json',
'image': 'glance_policy.json',
- 'orchestration': 'heat_policy.json',
'network': 'neutron_policy.json',
}
@@ -1103,29 +1102,6 @@ Default:
Used to customize features related to the image service, such as the list of
supported image formats.
-Heat
-----
-
-OPENSTACK_HEAT_STACK
-~~~~~~~~~~~~~~~~~~~~
-
-.. versionadded:: 9.0.0(Mitaka)
-
-Default:
-
-.. code-block:: python
-
- {
- 'enable_user_pass': True
- }
-
-A dictionary of settings to use with heat stacks. Currently, the only setting
-available is "enable_user_pass", which can be used to disable the password
-field while launching the stack. Currently HEAT API needs user password to
-perform all the heat operations because in HEAT API trusts is not enabled by
-default. So, this setting can be set as "False" in-case HEAT uses trusts by
-default otherwise it needs to be set as "True".
-
Keystone
--------
diff --git a/doc/source/contributor/quickstart.rst b/doc/source/contributor/quickstart.rst
index b464a9e03f..e903139ecc 100644
--- a/doc/source/contributor/quickstart.rst
+++ b/doc/source/contributor/quickstart.rst
@@ -83,7 +83,7 @@ To start the Horizon development server use the command below
.. note::
- The default port for runserver is 8000 which is already consumed by
+ The default port for runserver is 8000 which might be already consumed by
heat-api-cfn in DevStack. If running in DevStack
``tox -e runserver -- localhost:9000`` will start the test server at
``http://localhost:9000``
diff --git a/doc/source/contributor/ref/local_conf.rst b/doc/source/contributor/ref/local_conf.rst
index 813a51f5bf..7066712b4f 100644
--- a/doc/source/contributor/ref/local_conf.rst
+++ b/doc/source/contributor/ref/local_conf.rst
@@ -69,9 +69,6 @@ see https://docs.openstack.org/devstack/latest/
SWIFT_REPLICAS=1
SWIFT_DATA_DIR=$DEST/data/swift
- # Enable Heat
- enable_plugin heat https://git.openstack.org/openstack/heat
-
# Enable Neutron
enable_plugin neutron https://git.openstack.org/openstack/neutron
diff --git a/doc/source/install/from-source.rst b/doc/source/install/from-source.rst
index d34492c0ee..c0ca1e1f45 100644
--- a/doc/source/install/from-source.rst
+++ b/doc/source/install/from-source.rst
@@ -22,7 +22,6 @@ System Requirements
* `cinder `_: Block Storage
* `glance `_: Image Management
- * `heat `_: Orchestration
* `neutron `_: Networking
* `nova `_: Compute
* `swift `_: Object Storage
diff --git a/doc/source/user/index.rst b/doc/source/user/index.rst
index cde57d3cc2..0112c3ef5f 100644
--- a/doc/source/user/index.rst
+++ b/doc/source/user/index.rst
@@ -18,7 +18,6 @@ sizes of server instances.
manage-containers.rst
manage-volumes.rst
manage-shares.rst
- stacks.rst
databases.rst
manage-lbaasv2.rst
browser_support
diff --git a/doc/source/user/log-in.rst b/doc/source/user/log-in.rst
index 0f80d6e24a..25b560fc7e 100644
--- a/doc/source/user/log-in.rst
+++ b/doc/source/user/log-in.rst
@@ -50,11 +50,6 @@ The dashboard is generally installed on the controller node.
(:ref:`dashboard-admin-tab`) and :guilabel:`Identity` tab
(:ref:`dashboard-identity-tab`) are displayed.
-.. note::
-
- Some tabs, such as :guilabel:`Orchestration` and :guilabel:`Firewalls`,
- only appear on the dashboard if they are properly configured.
-
.. _dashboard-project-tab:
OpenStack dashboard — Project tab
@@ -143,15 +138,6 @@ Network tab
* :guilabel:`Firewall Rules`: Add and manage firewall rules.
-Orchestration tab
------------------
-
-* :guilabel:`Stacks`: Use the REST API to orchestrate multiple composite
- cloud applications.
-
-* :guilabel:`Resource Types`: Show a list of all the supported resource
- types for HOT templates.
-
Object Store tab
----------------
@@ -234,9 +220,6 @@ System tab
* :guilabel:`Network Agents`: View the network agents.
- * :guilabel:`Orchestration Services`: View a list of all Orchestration
- services.
-
* :guilabel:`Shares`: Use the following tabs to complete these tasks:
* :guilabel:`Shares`: View, create, manage, and delete shares.
diff --git a/doc/source/user/stacks.rst b/doc/source/user/stacks.rst
deleted file mode 100644
index 7767976b96..0000000000
--- a/doc/source/user/stacks.rst
+++ /dev/null
@@ -1,149 +0,0 @@
-========================
-Launch and manage stacks
-========================
-
-OpenStack Orchestration is a service that you can use to
-orchestrate multiple composite cloud applications. This
-service supports the use of both the Amazon Web Services (AWS)
-CloudFormation template format through both a Query API that
-is compatible with CloudFormation and the native OpenStack
-Heat Orchestration Template (HOT) format through a REST API.
-
-These flexible template languages enable application
-developers to describe and automate the deployment of
-infrastructure, services, and applications. The templates
-enable creation of most OpenStack resource types, such as
-instances, floating IP addresses, volumes, security groups,
-and users. Once created, the resources are referred to as
-stacks.
-
-The template languages are described in the `Template Guide
- `_.
-
-Launch a stack
-~~~~~~~~~~~~~~
-
-#. Log in to the dashboard.
-#. Select the appropriate project from the drop down menu at the top left.
-#. On the :guilabel:`Project` tab, open the :guilabel:`Orchestration` tab and
- click :guilabel:`Stacks` category.
-#. Click :guilabel:`Launch Stack`.
-#. In the :guilabel:`Select Template` dialog box, specify the
- following values:
-
- +---------------------------------------+-------------------------------+
- | :guilabel:`Template Source` | Choose the source of the |
- | | template from the list. |
- +---------------------------------------+-------------------------------+
- | :guilabel:`Template URL/File/Data` | Depending on the source that |
- | | you select, enter the URL, |
- | | browse to the file location, |
- | | or directly include the |
- | | template. |
- +---------------------------------------+-------------------------------+
- | :guilabel:`Environment Source` | Choose the source of the |
- | | environment from the list. |
- | | The environment files contain |
- | | additional settings for the |
- | | stack. |
- +---------------------------------------+-------------------------------+
- | :guilabel:`Environment File/Data` | Depending on the source that |
- | | you select, browse to the |
- | | file location, directly |
- | | include the environment |
- +---------------------------------------+-------------------------------+
-
-#. Click :guilabel:`Next`.
-#. In the :guilabel:`Launch Stack` dialog box, specify the
- following values:
-
- +---------------------------------+---------------------------------+
- | :guilabel:`Stack Name` | Enter a name to identify |
- | | the stack. |
- +---------------------------------+---------------------------------+
- | :guilabel:`Creation Timeout` | Specify the number of minutes |
- | :guilabel:`(minutes)` | that can elapse before the |
- | | launch of the stack times out. |
- +---------------------------------+---------------------------------+
- | :guilabel:`Rollback On Failure` | Select this check box if you |
- | | want the service to roll back |
- | | changes if the stack fails to |
- | | launch. |
- +---------------------------------+---------------------------------+
- | :guilabel:`Password for user` | Specify the password that |
- | :guilabel:`"demo"` | the default user uses when the |
- | | stack is created. |
- +---------------------------------+---------------------------------+
- | :guilabel:`DBUsername` | Specify the name of the |
- | | database user. |
- +---------------------------------+---------------------------------+
- | :guilabel:`LinuxDistribution` | Specify the Linux distribution |
- | | that is used in the stack. |
- +---------------------------------+---------------------------------+
- | :guilabel:`DBRootPassword` | Specify the root password for |
- | | the database. |
- +---------------------------------+---------------------------------+
- | :guilabel:`KeyName` | Specify the name of the key pair|
- | | to use to log in to the stack. |
- +---------------------------------+---------------------------------+
- | :guilabel:`DBName` | Specify the name of the |
- | | database. |
- +---------------------------------+---------------------------------+
- | :guilabel:`DBPassword` | Specify the password of the |
- | | database. |
- +---------------------------------+---------------------------------+
- | :guilabel:`InstanceType` | Specify the flavor for the |
- | | instance. |
- +---------------------------------+---------------------------------+
-
-#. Click :guilabel:`Launch` to create a stack. The :guilabel:`Stacks`
- tab shows the stack.
-
-After the stack is created, click on the stack name to see the
-following details:
-
-Topology
- The topology of the stack.
-
-Overview
- The parameters and details of the stack.
-
-Resources
- The resources used by the stack.
-
-Events
- The events related to the stack.
-
-Template
- The template for the stack.
-
-Manage a stack
-~~~~~~~~~~~~~~
-
-#. Log in to the dashboard.
-#. Select the appropriate project from the drop down menu at the top left.
-#. On the :guilabel:`Project` tab, open the :guilabel:`Orchestration` tab and
- click :guilabel:`Stacks` category.
-#. Select the stack that you want to update.
-#. Click :guilabel:`Change Stack Template`.
-#. In the :guilabel:`Select Template` dialog box, select the
- new template source or environment source.
-#. Click :guilabel:`Next`.
-
- The :guilabel:`Update Stack Parameters` window appears.
-#. Enter new values for any parameters that you want to update.
-#. Click :guilabel:`Update`.
-
-Delete a stack
-~~~~~~~~~~~~~~
-
-When you delete a stack, you cannot undo this action.
-
-#. Log in to the dashboard.
-#. Select the appropriate project from the drop down menu at the top left.
-#. On the :guilabel:`Project` tab, open the :guilabel:`Orchestration` tab and
- click :guilabel:`Stacks` category.
-#. Select the stack that you want to delete.
-#. Click :guilabel:`Delete Stack`.
-#. In the confirmation dialog box, click :guilabel:`Delete Stack`
- to confirm the deletion.
diff --git a/openstack_dashboard/api/__init__.py b/openstack_dashboard/api/__init__.py
index 6262470038..9483b39414 100644
--- a/openstack_dashboard/api/__init__.py
+++ b/openstack_dashboard/api/__init__.py
@@ -34,7 +34,6 @@ Keystone/Nova/Glance/Swift et. al.
from openstack_dashboard.api import base
from openstack_dashboard.api import cinder
from openstack_dashboard.api import glance
-from openstack_dashboard.api import heat
from openstack_dashboard.api import keystone
from openstack_dashboard.api import network
from openstack_dashboard.api import neutron
@@ -46,7 +45,6 @@ __all__ = [
"base",
"cinder",
"glance",
- "heat",
"keystone",
"network",
"neutron",
diff --git a/openstack_dashboard/api/heat.py b/openstack_dashboard/api/heat.py
deleted file mode 100644
index c31c61dad9..0000000000
--- a/openstack_dashboard/api/heat.py
+++ /dev/null
@@ -1,265 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import contextlib
-
-from django.conf import settings
-from heatclient import client as heat_client
-from heatclient.common import template_format
-from heatclient.common import template_utils
-from heatclient.common import utils as heat_utils
-from oslo_serialization import jsonutils
-import six
-from six.moves.urllib import request
-
-from horizon import exceptions
-from horizon.utils import functions as utils
-from horizon.utils.memoized import memoized
-from openstack_dashboard.api import base
-from openstack_dashboard.contrib.developer.profiler import api as profiler
-
-
-def format_parameters(params):
- parameters = {}
- for count, p in enumerate(params, 1):
- parameters['Parameters.member.%d.ParameterKey' % count] = p
- parameters['Parameters.member.%d.ParameterValue' % count] = params[p]
- return parameters
-
-
-@memoized
-def heatclient(request, password=None):
- api_version = "1"
- insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
- cacert = getattr(settings, 'OPENSTACK_SSL_CACERT', None)
- endpoint = base.url_for(request, 'orchestration')
- kwargs = {
- 'token': request.user.token.id,
- 'insecure': insecure,
- 'ca_file': cacert,
- 'username': request.user.username,
- 'password': password
- # 'timeout': args.timeout,
- # 'ca_file': args.ca_file,
- # 'cert_file': args.cert_file,
- # 'key_file': args.key_file,
- }
- client = heat_client.Client(api_version, endpoint, **kwargs)
- client.format_parameters = format_parameters
- return client
-
-
-@profiler.trace
-def stacks_list(request, marker=None, sort_dir='desc', sort_key='created_at',
- paginate=False, filters=None):
- limit = getattr(settings, 'API_RESULT_LIMIT', 1000)
- page_size = utils.get_page_size(request)
-
- if paginate:
- request_size = page_size + 1
- else:
- request_size = limit
-
- kwargs = {'sort_dir': sort_dir, 'sort_key': sort_key}
- if marker:
- kwargs['marker'] = marker
-
- if filters:
- kwargs.update(filters)
- if 'status' in kwargs:
- kwargs['status'] = kwargs['status'].replace(' ', '_').upper()
-
- stacks_iter = heatclient(request).stacks.list(limit=request_size,
- **kwargs)
-
- has_prev_data = False
- has_more_data = False
- stacks = list(stacks_iter)
-
- if paginate:
- if len(stacks) > page_size:
- stacks.pop()
- has_more_data = True
- if marker is not None:
- has_prev_data = True
- elif sort_dir == 'asc' and marker is not None:
- has_more_data = True
- elif marker is not None:
- has_prev_data = True
- return (stacks, has_more_data, has_prev_data)
-
-
-def _ignore_if(key, value):
- if key != 'get_file' and key != 'type':
- return True
- if not isinstance(value, six.string_types):
- return True
- if (key == 'type' and
- not value.endswith(('.yaml', '.template'))):
- return True
- return False
-
-
-@profiler.trace
-def get_template_files(template_data=None, template_url=None):
- if template_data:
- tpl = template_data
- elif template_url:
- with contextlib.closing(request.urlopen(template_url)) as u:
- tpl = u.read()
- else:
- return {}, None
- if not tpl:
- return {}, None
- if isinstance(tpl, six.binary_type):
- tpl = tpl.decode('utf-8')
- template = template_format.parse(tpl)
- files = {}
- _get_file_contents(template, files)
- return files, template
-
-
-def _get_file_contents(from_data, files):
- if not isinstance(from_data, (dict, list)):
- return
- if isinstance(from_data, dict):
- recurse_data = from_data.values()
- for key, value in from_data.items():
- if _ignore_if(key, value):
- continue
- if not value.startswith(('http://', 'https://')):
- raise exceptions.GetFileError(value, 'get_file')
- if value not in files:
- file_content = heat_utils.read_url_content(value)
- if template_utils.is_template(file_content):
- template = get_template_files(template_url=value)[1]
- file_content = jsonutils.dumps(template)
- files[value] = file_content
- else:
- recurse_data = from_data
- for value in recurse_data:
- _get_file_contents(value, files)
-
-
-@profiler.trace
-def stack_delete(request, stack_id):
- return heatclient(request).stacks.delete(stack_id)
-
-
-@profiler.trace
-def stack_get(request, stack_id):
- return heatclient(request).stacks.get(stack_id)
-
-
-@profiler.trace
-def template_get(request, stack_id):
- return heatclient(request).stacks.template(stack_id)
-
-
-@profiler.trace
-def stack_create(request, password=None, **kwargs):
- return heatclient(request, password).stacks.create(**kwargs)
-
-
-@profiler.trace
-def stack_preview(request, password=None, **kwargs):
- return heatclient(request, password).stacks.preview(**kwargs)
-
-
-@profiler.trace
-def stack_update(request, stack_id, password=None, **kwargs):
- return heatclient(request, password).stacks.update(stack_id, **kwargs)
-
-
-@profiler.trace
-def snapshot_create(request, stack_id):
- return heatclient(request).stacks.snapshot(stack_id)
-
-
-@profiler.trace
-def snapshot_list(request, stack_id):
- return heatclient(request).stacks.snapshot_list(stack_id)
-
-
-@profiler.trace
-def snapshot_show(request, stack_id, snapshot_id):
- return heatclient(request).stacks.snapshot_show(stack_id, snapshot_id)
-
-
-@profiler.trace
-def snapshot_delete(request, stack_id, snapshot_id):
- return heatclient(request).stacks.snapshot_delete(stack_id, snapshot_id)
-
-
-@profiler.trace
-def events_list(request, stack_name):
- return heatclient(request).events.list(stack_name)
-
-
-@profiler.trace
-def resources_list(request, stack_name):
- return heatclient(request).resources.list(stack_name)
-
-
-@profiler.trace
-def resource_get(request, stack_id, resource_name):
- return heatclient(request).resources.get(stack_id, resource_name)
-
-
-@profiler.trace
-def resource_metadata_get(request, stack_id, resource_name):
- return heatclient(request).resources.metadata(stack_id, resource_name)
-
-
-@profiler.trace
-def template_validate(request, **kwargs):
- return heatclient(request).stacks.validate(**kwargs)
-
-
-@profiler.trace
-def action_check(request, stack_id):
- return heatclient(request).actions.check(stack_id)
-
-
-@profiler.trace
-def action_suspend(request, stack_id):
- return heatclient(request).actions.suspend(stack_id)
-
-
-@profiler.trace
-def action_resume(request, stack_id):
- return heatclient(request).actions.resume(stack_id)
-
-
-@profiler.trace
-def resource_types_list(request, filters=None):
- return heatclient(request).resource_types.list(filters=filters)
-
-
-@profiler.trace
-def resource_type_get(request, resource_type):
- return heatclient(request).resource_types.get(resource_type)
-
-
-@profiler.trace
-def service_list(request):
- return heatclient(request).services.list()
-
-
-@profiler.trace
-def template_version_list(request):
- return heatclient(request).template_versions.list()
-
-
-@profiler.trace
-def template_function_list(request, template_version):
- return heatclient(request).template_versions.get(template_version)
diff --git a/openstack_dashboard/api/rest/__init__.py b/openstack_dashboard/api/rest/__init__.py
index 925cbb098f..11df2d5294 100644
--- a/openstack_dashboard/api/rest/__init__.py
+++ b/openstack_dashboard/api/rest/__init__.py
@@ -24,7 +24,6 @@ in https://wiki.openstack.org/wiki/APIChangeGuidelines.
from openstack_dashboard.api.rest import cinder
from openstack_dashboard.api.rest import config
from openstack_dashboard.api.rest import glance
-from openstack_dashboard.api.rest import heat
from openstack_dashboard.api.rest import keystone
from openstack_dashboard.api.rest import network
from openstack_dashboard.api.rest import neutron
@@ -37,7 +36,6 @@ __all__ = [
'cinder',
'config',
'glance',
- 'heat',
'keystone',
'network',
'neutron',
diff --git a/openstack_dashboard/api/rest/heat.py b/openstack_dashboard/api/rest/heat.py
deleted file mode 100644
index df8752f1f8..0000000000
--- a/openstack_dashboard/api/rest/heat.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""API for the heat service."""
-
-from django.views import generic
-
-from openstack_dashboard import api
-from openstack_dashboard.api.rest import urls
-from openstack_dashboard.api.rest import utils as rest_utils
-
-
-@urls.register
-class Validate(generic.View):
- """API for validating a template"""
- url_regex = r'heat/validate/$'
-
- @rest_utils.ajax(data_required=True)
- def post(self, request):
- """Validate a template
-
- The following parameters may be passed in the POST
- application/json object. The parameters are:
- request:
-
- :param template_url: The template to validate
- """
- return api.heat.template_validate(request, **(request.DATA))
-
-
-@urls.register
-class Services(generic.View):
- """API for heat services."""
- url_regex = r'heat/services/$'
-
- @rest_utils.ajax()
- def get(self, request):
- """Get a list of heat services."""
- if api.base.is_service_enabled(request, 'orchestration'):
- result = api.heat.service_list(request)
- return {'items': [u.to_dict() for u in result]}
- else:
- raise rest_utils.AjaxError(501, '')
diff --git a/openstack_dashboard/conf/heat_policy.json b/openstack_dashboard/conf/heat_policy.json
deleted file mode 100644
index b40b1eef2e..0000000000
--- a/openstack_dashboard/conf/heat_policy.json
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- "context_is_admin": "role:admin",
- "deny_stack_user": "not role:heat_stack_user",
- "deny_everybody": "!",
-
- "cloudformation:ListStacks": "rule:deny_stack_user",
- "cloudformation:CreateStack": "rule:deny_stack_user",
- "cloudformation:DescribeStacks": "rule:deny_stack_user",
- "cloudformation:DeleteStack": "rule:deny_stack_user",
- "cloudformation:UpdateStack": "rule:deny_stack_user",
- "cloudformation:CancelUpdateStack": "rule:deny_stack_user",
- "cloudformation:DescribeStackEvents": "rule:deny_stack_user",
- "cloudformation:ValidateTemplate": "rule:deny_stack_user",
- "cloudformation:GetTemplate": "rule:deny_stack_user",
- "cloudformation:EstimateTemplateCost": "rule:deny_stack_user",
- "cloudformation:DescribeStackResource": "",
- "cloudformation:DescribeStackResources": "rule:deny_stack_user",
- "cloudformation:ListStackResources": "rule:deny_stack_user",
-
- "cloudwatch:DeleteAlarms": "rule:deny_stack_user",
- "cloudwatch:DescribeAlarmHistory": "rule:deny_stack_user",
- "cloudwatch:DescribeAlarms": "rule:deny_stack_user",
- "cloudwatch:DescribeAlarmsForMetric": "rule:deny_stack_user",
- "cloudwatch:DisableAlarmActions": "rule:deny_stack_user",
- "cloudwatch:EnableAlarmActions": "rule:deny_stack_user",
- "cloudwatch:GetMetricStatistics": "rule:deny_stack_user",
- "cloudwatch:ListMetrics": "rule:deny_stack_user",
- "cloudwatch:PutMetricAlarm": "rule:deny_stack_user",
- "cloudwatch:PutMetricData": "",
- "cloudwatch:SetAlarmState": "rule:deny_stack_user",
-
- "actions:action": "rule:deny_stack_user",
- "build_info:build_info": "rule:deny_stack_user",
- "events:index": "rule:deny_stack_user",
- "events:show": "rule:deny_stack_user",
- "resource:index": "rule:deny_stack_user",
- "resource:metadata": "",
- "resource:signal": "",
- "resource:mark_unhealthy": "rule:deny_stack_user",
- "resource:show": "rule:deny_stack_user",
- "stacks:abandon": "rule:deny_stack_user",
- "stacks:create": "rule:deny_stack_user",
- "stacks:delete": "rule:deny_stack_user",
- "stacks:detail": "rule:deny_stack_user",
- "stacks:export": "rule:deny_stack_user",
- "stacks:generate_template": "rule:deny_stack_user",
- "stacks:global_index": "rule:deny_everybody",
- "stacks:index": "rule:deny_stack_user",
- "stacks:list_resource_types": "rule:deny_stack_user",
- "stacks:list_template_versions": "rule:deny_stack_user",
- "stacks:list_template_functions": "rule:deny_stack_user",
- "stacks:lookup": "",
- "stacks:preview": "rule:deny_stack_user",
- "stacks:resource_schema": "rule:deny_stack_user",
- "stacks:show": "rule:deny_stack_user",
- "stacks:template": "rule:deny_stack_user",
- "stacks:environment": "rule:deny_stack_user",
- "stacks:update": "rule:deny_stack_user",
- "stacks:update_patch": "rule:deny_stack_user",
- "stacks:preview_update": "rule:deny_stack_user",
- "stacks:preview_update_patch": "rule:deny_stack_user",
- "stacks:validate_template": "rule:deny_stack_user",
- "stacks:snapshot": "rule:deny_stack_user",
- "stacks:show_snapshot": "rule:deny_stack_user",
- "stacks:delete_snapshot": "rule:deny_stack_user",
- "stacks:list_snapshots": "rule:deny_stack_user",
- "stacks:restore_snapshot": "rule:deny_stack_user",
- "stacks:list_outputs": "rule:deny_stack_user",
- "stacks:show_output": "rule:deny_stack_user",
-
- "software_configs:global_index": "rule:deny_everybody",
- "software_configs:index": "rule:deny_stack_user",
- "software_configs:create": "rule:deny_stack_user",
- "software_configs:show": "rule:deny_stack_user",
- "software_configs:delete": "rule:deny_stack_user",
- "software_deployments:index": "rule:deny_stack_user",
- "software_deployments:create": "rule:deny_stack_user",
- "software_deployments:show": "rule:deny_stack_user",
- "software_deployments:update": "rule:deny_stack_user",
- "software_deployments:delete": "rule:deny_stack_user",
- "software_deployments:metadata": "",
-
- "service:index": "rule:context_is_admin",
-
- "resource_types:OS::Nova::Flavor": "rule:context_is_admin",
- "resource_types:OS::Cinder::EncryptedVolumeType": "rule:context_is_admin",
- "resource_types:OS::Cinder::VolumeType": "rule:context_is_admin",
- "resource_types:OS::Manila::ShareType": "rule:context_is_admin",
- "resource_types:OS::Neutron::QoSPolicy": "rule:context_is_admin",
- "resource_types:OS::Neutron::QoSBandwidthLimitRule": "rule:context_is_admin",
- "resource_types:OS::Nova::HostAggregate": "rule:context_is_admin"
-}
diff --git a/openstack_dashboard/dashboards/admin/dashboard.py b/openstack_dashboard/dashboards/admin/dashboard.py
index a1eb5feb2f..f526d957b7 100644
--- a/openstack_dashboard/dashboards/admin/dashboard.py
+++ b/openstack_dashboard/dashboards/admin/dashboard.py
@@ -28,8 +28,7 @@ class Admin(horizon.Dashboard):
('image', 'context_is_admin'),
('volume', 'context_is_admin'),
('compute', 'context_is_admin'),
- ('network', 'context_is_admin'),
- ('orchestration', 'context_is_admin'),)
+ ('network', 'context_is_admin'),)
else:
permissions = (tuple(utils.get_admin_permissions()),)
diff --git a/openstack_dashboard/dashboards/admin/info/panel.py b/openstack_dashboard/dashboards/admin/info/panel.py
index 8979032d5c..85a9642449 100644
--- a/openstack_dashboard/dashboards/admin/info/panel.py
+++ b/openstack_dashboard/dashboards/admin/info/panel.py
@@ -26,5 +26,4 @@ class Info(horizon.Panel):
slug = 'info'
policy_rules = (("compute", "context_is_admin"),
("volume", "context_is_admin"),
- ("network", "context_is_admin"),
- ("orchestration", "context_is_admin"),)
+ ("network", "context_is_admin"),)
diff --git a/openstack_dashboard/dashboards/admin/info/tables.py b/openstack_dashboard/dashboards/admin/info/tables.py
index 44f0758ebc..40894f0e0c 100644
--- a/openstack_dashboard/dashboards/admin/info/tables.py
+++ b/openstack_dashboard/dashboards/admin/info/tables.py
@@ -236,45 +236,3 @@ class NetworkAgentsTable(tables.DataTable):
table_actions = (NetworkAgentsFilterAction, )
row_actions = (NetworkL3AgentRoutersLinkAction, )
multi_select = False
-
-
-class HeatServiceFilterAction(tables.FilterAction):
- filter_field = 'type'
-
- def filter(self, table, services, filter_string):
- q = filter_string.lower()
-
- def comp(service):
- attr = getattr(service, self.filter_field, '')
- if attr is not None and q in attr.lower():
- return True
- return False
-
- return filter(comp, services)
-
-
-class HeatServiceTable(tables.DataTable):
- hostname = tables.Column('hostname', verbose_name=_('Hostname'))
- binary = tables.Column("binary", verbose_name=_('Name'))
- engine_id = tables.Column('engine_id', verbose_name=_('Engine Id'))
- host = tables.Column('host', verbose_name=_('Host'))
- topic = tables.Column('topic', verbose_name=_('Topic'))
- # For consistent with other tables in system info, set column name to
- # 'state'
- state = tables.Column('status', verbose_name=_('State'),
- display_choices=SERVICE_STATE_DISPLAY_CHOICES)
- updated_at = tables.Column('updated_at',
- verbose_name=pgettext_lazy(
- 'Time since the last update',
- u'Last Updated'),
- filters=(utils_filters.parse_isotime,
- filters.timesince))
-
- def get_object_id(self, obj):
- return "%s" % obj.engine_id
-
- class Meta(object):
- name = "heat_services"
- verbose_name = _("Orchestration Services")
- table_actions = (HeatServiceFilterAction,)
- multi_select = False
diff --git a/openstack_dashboard/dashboards/admin/info/tabs.py b/openstack_dashboard/dashboards/admin/info/tabs.py
index cdda728073..5cd265fd1f 100644
--- a/openstack_dashboard/dashboards/admin/info/tabs.py
+++ b/openstack_dashboard/dashboards/admin/info/tabs.py
@@ -18,7 +18,6 @@ from horizon import exceptions
from horizon import tabs
from openstack_dashboard.api import base
from openstack_dashboard.api import cinder
-from openstack_dashboard.api import heat
from openstack_dashboard.api import neutron
from openstack_dashboard.api import nova
from openstack_dashboard.dashboards.admin.info import constants
@@ -118,32 +117,8 @@ class NetworkAgentsTab(tabs.TableTab):
return agents
-class HeatServiceTab(tabs.TableTab):
- table_classes = (tables.HeatServiceTable,)
- name = tables.HeatServiceTable.Meta.verbose_name
- slug = tables.HeatServiceTable.Meta.name
- template_name = constants.INFO_DETAIL_TEMPLATE_NAME
-
- def allowed(self, request):
- try:
- return base.is_service_enabled(request, 'orchestration')
- except Exception:
- exceptions.handle(request, _('Orchestration service is disabled.'))
- return False
-
- def get_heat_services_data(self):
- try:
- services = heat.service_list(self.tab_group.request)
- except Exception:
- msg = _('Unable to get Orchestration service list.')
- exceptions.check_message(["Connection", "refused"], msg)
- exceptions.handle(self.request, msg)
- services = []
- return services
-
-
class SystemInfoTabs(tabs.TabGroup):
slug = "system_info"
tabs = (ServicesTab, NovaServicesTab, CinderServicesTab,
- NetworkAgentsTab, HeatServiceTab)
+ NetworkAgentsTab)
sticky = True
diff --git a/openstack_dashboard/dashboards/admin/info/tests.py b/openstack_dashboard/dashboards/admin/info/tests.py
index c7405d3ead..9cbe86594c 100644
--- a/openstack_dashboard/dashboards/admin/info/tests.py
+++ b/openstack_dashboard/dashboards/admin/info/tests.py
@@ -29,7 +29,7 @@ class SystemInfoViewTests(test.BaseAdminViewTests):
api.nova: ('service_list',),
api.neutron: ('agent_list', 'is_extension_supported'),
api.cinder: ('service_list',),
- api.heat: ('service_list',)})
+ })
def _test_base_index(self):
api.base.is_service_enabled(IsA(http.HttpRequest), IgnoreArg()) \
.MultipleTimes().AndReturn(True)
@@ -49,10 +49,6 @@ class SystemInfoViewTests(test.BaseAdminViewTests):
api.cinder.service_list(IsA(http.HttpRequest)).\
AndReturn(cinder_services)
- heat_services = self.heat_services.list()
- api.heat.service_list(IsA(http.HttpRequest)).\
- AndReturn(heat_services)
-
self.mox.ReplayAll()
res = self.client.get(INDEX_URL)
@@ -88,14 +84,3 @@ class SystemInfoViewTests(test.BaseAdminViewTests):
)
self.mox.VerifyAll()
-
- def test_heat_index(self):
- res = self._test_base_index()
- heat_services_tab = res.context['tab_group'].\
- get_tab('heat_services')
- self.assertQuerysetEqual(
- heat_services_tab._tables['heat_services'].data,
- [service.__repr__() for service in self.heat_services.list()]
- )
-
- self.mox.VerifyAll()
diff --git a/openstack_dashboard/dashboards/project/stacks/__init__.py b/openstack_dashboard/dashboards/project/stacks/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/openstack_dashboard/dashboards/project/stacks/api.py b/openstack_dashboard/dashboards/project/stacks/api.py
deleted file mode 100644
index ce5affd812..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/api.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import json
-
-from openstack_dashboard.api import heat
-
-from openstack_dashboard.dashboards.project.stacks import mappings
-from openstack_dashboard.dashboards.project.stacks import sro
-
-
-class Stack(object):
- pass
-
-
-def d3_data(request, stack_id=''):
- try:
- stack = heat.stack_get(request, stack_id)
- except Exception:
- stack = Stack()
- stack.id = stack_id
- stack.stack_name = request.session.get('stack_name', '')
- stack.stack_status = 'DELETE_COMPLETE'
- stack.stack_status_reason = 'DELETE_COMPLETE'
-
- try:
- resources = heat.resources_list(request, stack.stack_name)
- except Exception:
- resources = []
-
- d3_data = {"nodes": [], "stack": {}}
- if stack:
- stack_image = mappings.get_resource_image(stack.stack_status, 'stack')
- stack_node = {
- 'stack_id': stack.id,
- 'name': stack.stack_name,
- 'status': stack.stack_status,
- 'image': stack_image,
- 'image_size': 60,
- 'image_x': -30,
- 'image_y': -30,
- 'text_x': 40,
- 'text_y': ".35em",
- 'in_progress': (stack.status == 'IN_PROGRESS'),
- 'info_box': sro.stack_info(stack, stack_image)
- }
- d3_data['stack'] = stack_node
-
- if resources:
- for resource in resources:
- resource_image = mappings.get_resource_image(
- resource.resource_status,
- resource.resource_type)
- resource_status = mappings.get_resource_status(
- resource.resource_status)
- if resource_status in ('IN_PROGRESS', 'INIT'):
- in_progress = True
- else:
- in_progress = False
- resource_node = {
- 'name': resource.resource_name,
- 'status': resource.resource_status,
- 'image': resource_image,
- 'required_by': resource.required_by,
- 'image_size': 50,
- 'image_x': -25,
- 'image_y': -25,
- 'text_x': 35,
- 'text_y': ".35em",
- 'in_progress': in_progress,
- 'info_box': sro.resource_info(resource)
- }
- d3_data['nodes'].append(resource_node)
- return json.dumps(d3_data)
diff --git a/openstack_dashboard/dashboards/project/stacks/forms.py b/openstack_dashboard/dashboards/project/stacks/forms.py
deleted file mode 100644
index e8b970299f..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/forms.py
+++ /dev/null
@@ -1,488 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import json
-import logging
-
-import django
-from django.conf import settings
-from django.utils import html
-from django.utils.translation import ugettext_lazy as _
-from django.views.decorators.debug import sensitive_variables
-
-from oslo_utils import strutils
-import six
-
-from horizon import exceptions
-from horizon import forms
-from horizon import messages
-
-from openstack_dashboard import api
-from openstack_dashboard.dashboards.project.images \
- import utils as image_utils
-from openstack_dashboard.dashboards.project.instances \
- import utils as instance_utils
-
-
-LOG = logging.getLogger(__name__)
-
-
-def create_upload_form_attributes(prefix, input_type, name):
- """Creates attribute dicts for the switchable upload form
-
- :type prefix: str
- :param prefix: prefix (environment, template) of field
- :type input_type: str
- :param input_type: field type (file, raw, url)
- :type name: str
- :param name: translated text label to display to user
- :rtype: dict
- :return: an attribute set to pass to form build
- """
- attributes = {'class': 'switched', 'data-switch-on': prefix + 'source'}
- attributes['data-' + prefix + 'source-' + input_type] = name
- return attributes
-
-
-class TemplateForm(forms.SelfHandlingForm):
-
- class Meta(object):
- name = _('Select Template')
- help_text = _('Select a template to launch a stack.')
-
- # TODO(jomara) - update URL choice for template & environment files
- # w/ client side download when applicable
- base_choices = [('file', _('File')),
- ('raw', _('Direct Input'))]
- url_choice = [('url', _('URL'))]
- attributes = {'class': 'switchable', 'data-slug': 'templatesource'}
- template_source = forms.ChoiceField(label=_('Template Source'),
- choices=base_choices + url_choice,
- widget=forms.ThemableSelectWidget(
- attrs=attributes))
-
- attributes = create_upload_form_attributes(
- 'template',
- 'file',
- _('Template File'))
- template_upload = forms.FileField(
- label=_('Template File'),
- help_text=_('A local template to upload.'),
- widget=forms.FileInput(attrs=attributes),
- required=False)
-
- attributes = create_upload_form_attributes(
- 'template',
- 'url',
- _('Template URL'))
- template_url = forms.URLField(
- label=_('Template URL'),
- help_text=_('An external (HTTP) URL to load the template from.'),
- widget=forms.TextInput(attrs=attributes),
- required=False)
-
- attributes = create_upload_form_attributes(
- 'template',
- 'raw',
- _('Template Data'))
- template_data = forms.CharField(
- label=_('Template Data'),
- help_text=_('The raw contents of the template.'),
- widget=forms.widgets.Textarea(attrs=attributes),
- required=False)
-
- attributes = {'data-slug': 'envsource', 'class': 'switchable'}
- environment_source = forms.ChoiceField(
- label=_('Environment Source'),
- choices=base_choices,
- widget=forms.ThemableSelectWidget(attrs=attributes),
- required=False)
-
- attributes = create_upload_form_attributes(
- 'env',
- 'file',
- _('Environment File'))
- environment_upload = forms.FileField(
- label=_('Environment File'),
- help_text=_('A local environment to upload.'),
- widget=forms.FileInput(attrs=attributes),
- required=False)
-
- attributes = create_upload_form_attributes(
- 'env',
- 'raw',
- _('Environment Data'))
- environment_data = forms.CharField(
- label=_('Environment Data'),
- help_text=_('The raw contents of the environment file.'),
- widget=forms.widgets.Textarea(attrs=attributes),
- required=False)
-
- if django.VERSION >= (1, 9):
- # Note(Itxaka): On django>=1.9 Charfield has an strip option that
- # we need to set to False as to not hit
- # https://bugs.launchpad.net/python-heatclient/+bug/1546166
- environment_data.strip = False
- template_data.strip = False
-
- def __init__(self, *args, **kwargs):
- self.next_view = kwargs.pop('next_view')
- super(TemplateForm, self).__init__(*args, **kwargs)
-
- def clean(self):
- cleaned = super(TemplateForm, self).clean()
-
- files = self.request.FILES
- self.clean_uploaded_files('template', _('template'), cleaned, files)
- self.clean_uploaded_files('environment', _('environment'), cleaned,
- files)
-
- # Validate the template and get back the params.
- kwargs = {}
- if cleaned['environment_data']:
- kwargs['environment'] = cleaned['environment_data']
- try:
- files, tpl =\
- api.heat.get_template_files(cleaned.get('template_data'),
- cleaned.get('template_url'))
- kwargs['files'] = files
- kwargs['template'] = tpl
- validated = api.heat.template_validate(self.request, **kwargs)
- cleaned['template_validate'] = validated
- cleaned['template_validate']['files'] = files
- cleaned['template_validate']['template'] = tpl
- except Exception as e:
- raise forms.ValidationError(six.text_type(e))
-
- return cleaned
-
- def clean_uploaded_files(self, prefix, field_label, cleaned, files):
- """Cleans Template & Environment data from form upload.
-
- Does some of the crunchy bits for processing uploads vs raw
- data depending on what the user specified. Identical process
- for environment data & template data.
-
- :type prefix: str
- :param prefix: prefix (environment, template) of field
- :type field_label: str
- :param field_label: translated prefix str for messages
- :type input_type: dict
- :param prefix: existing cleaned fields from form
- :rtype: dict
- :return: cleaned dict including environment & template data
- """
-
- upload_str = prefix + "_upload"
- data_str = prefix + "_data"
- url = cleaned.get(prefix + '_url')
- data = cleaned.get(prefix + '_data')
-
- has_upload = upload_str in files
- # Uploaded file handler
- if has_upload and not url:
- log_template_name = files[upload_str].name
- LOG.info('got upload %s', log_template_name)
-
- tpl = files[upload_str].read()
- if tpl.startswith('{'):
- try:
- json.loads(tpl)
- except Exception as e:
- msg = _('There was a problem parsing the'
- ' %(prefix)s: %(error)s')
- msg = msg % {'prefix': prefix, 'error': six.text_type(e)}
- raise forms.ValidationError(msg)
- cleaned[data_str] = tpl
-
- # URL handler
- elif url and (has_upload or data):
- msg = _('Please specify a %s using only one source method.')
- msg = msg % field_label
- raise forms.ValidationError(msg)
-
- elif prefix == 'template':
- # Check for raw template input - blank environment allowed
- if not url and not data:
- msg = _('You must specify a template via one of the '
- 'available sources.')
- raise forms.ValidationError(msg)
-
- def create_kwargs(self, data):
- kwargs = {'parameters': data['template_validate'],
- 'environment_data': data['environment_data']}
- if data.get('stack_id'):
- kwargs['stack_id'] = data['stack_id']
- return kwargs
-
- def handle(self, request, data):
- kwargs = self.create_kwargs(data)
- # NOTE (gabriel): This is a bit of a hack, essentially rewriting this
- # request so that we can chain it as an input to the next view...
- # but hey, it totally works.
- request.method = 'GET'
-
- return self.next_view.as_view()(request, **kwargs)
-
-
-class ChangeTemplateForm(TemplateForm):
- class Meta(object):
- name = _('Edit Template')
- help_text = _('Select a new template to re-launch a stack.')
- stack_id = forms.CharField(label=_('Stack ID'),
- widget=forms.widgets.HiddenInput)
- stack_name = forms.CharField(label=_('Stack Name'),
- widget=forms.TextInput(attrs={'readonly':
- 'readonly'}))
-
-
-class PreviewTemplateForm(TemplateForm):
- class Meta(object):
- name = _('Preview Template')
- help_text = _('Select a new template to preview a stack.')
-
-
-class CreateStackForm(forms.SelfHandlingForm):
-
- param_prefix = '__param_'
-
- class Meta(object):
- name = _('Create Stack')
-
- environment_data = forms.CharField(
- widget=forms.widgets.HiddenInput,
- required=False)
- if django.VERSION >= (1, 9):
- # Note(Itxaka): On django>=1.9 Charfield has an strip option that
- # we need to set to False as to not hit
- # https://bugs.launchpad.net/python-heatclient/+bug/1546166
- environment_data.strip = False
-
- parameters = forms.CharField(
- widget=forms.widgets.HiddenInput)
- stack_name = forms.RegexField(
- max_length=255,
- label=_('Stack Name'),
- help_text=_('Name of the stack to create.'),
- regex=r"^[a-zA-Z][a-zA-Z0-9_.-]*$",
- error_messages={'invalid':
- _('Name must start with a letter and may '
- 'only contain letters, numbers, underscores, '
- 'periods and hyphens.')})
- timeout_mins = forms.IntegerField(
- initial=60,
- label=_('Creation Timeout (minutes)'),
- help_text=_('Stack creation timeout in minutes.'))
- enable_rollback = forms.BooleanField(
- label=_('Rollback On Failure'),
- help_text=_('Enable rollback on create/update failure.'),
- required=False)
-
- def __init__(self, *args, **kwargs):
- parameters = kwargs.pop('parameters')
- # special case: load template data from API, not passed in params
- if kwargs.get('validate_me'):
- parameters = kwargs.pop('validate_me')
- super(CreateStackForm, self).__init__(*args, **kwargs)
-
- if self._stack_password_enabled():
- self.fields['password'] = forms.CharField(
- label=_('Password for user "%s"') % self.request.user.username,
- help_text=_('This is required for operations to be performed '
- 'throughout the lifecycle of the stack'),
- widget=forms.PasswordInput())
-
- self._build_parameter_fields(parameters)
-
- def _stack_password_enabled(self):
- stack_settings = getattr(settings, 'OPENSTACK_HEAT_STACK', {})
- return stack_settings.get('enable_user_pass', True)
-
- def _build_parameter_fields(self, template_validate):
- self.help_text = template_validate['Description']
-
- params = template_validate.get('Parameters', {})
- if template_validate.get('ParameterGroups'):
- params_in_order = []
- for group in template_validate['ParameterGroups']:
- for param in group.get('parameters', []):
- if param in params:
- params_in_order.append((param, params[param]))
- else:
- # no parameter groups, simply sorted to make the order fixed
- params_in_order = sorted(params.items())
- for param_key, param in params_in_order:
- field = None
- field_key = self.param_prefix + param_key
- initial = param.get('Value',
- param.get('DefaultValue',
- param.get('Default')))
- field_args = {
- 'initial': initial,
- 'label': param.get('Label', param_key),
- 'help_text': html.escape(param.get('Description', '')),
- 'required': initial is None,
- }
-
- param_type = param.get('Type', None)
- hidden = strutils.bool_from_string(param.get('NoEcho', 'false'))
- if 'CustomConstraint' in param:
- choices = self._populate_custom_choices(
- param['CustomConstraint'])
- field_args['choices'] = choices
- field = forms.ChoiceField(**field_args)
-
- elif 'AllowedValues' in param:
- choices = map(lambda x: (x, x), param['AllowedValues'])
- field_args['choices'] = choices
- field = forms.ChoiceField(**field_args)
-
- elif param_type == 'Json' and 'Default' in param:
- field_args['initial'] = json.dumps(param['Default'])
- field = forms.CharField(**field_args)
-
- elif param_type in ('CommaDelimitedList', 'String', 'Json'):
- if 'MinLength' in param:
- field_args['min_length'] = int(param['MinLength'])
- field_args['required'] = field_args['min_length'] > 0
- if 'MaxLength' in param:
- field_args['max_length'] = int(param['MaxLength'])
- if hidden:
- field_args['widget'] = forms.PasswordInput(
- render_value=True)
- field = forms.CharField(**field_args)
-
- elif param_type == 'Number':
- if 'MinValue' in param:
- field_args['min_value'] = int(param['MinValue'])
- if 'MaxValue' in param:
- field_args['max_value'] = int(param['MaxValue'])
- field = forms.IntegerField(**field_args)
-
- elif param_type == 'Boolean':
- field_args['required'] = False
- field = forms.BooleanField(**field_args)
-
- if field:
- self.fields[field_key] = field
-
- @sensitive_variables('password')
- def handle(self, request, data):
- prefix_length = len(self.param_prefix)
- params_list = [(k[prefix_length:], v) for (k, v) in data.items()
- if k.startswith(self.param_prefix)]
- fields = {
- 'stack_name': data.get('stack_name'),
- 'timeout_mins': data.get('timeout_mins'),
- 'disable_rollback': not(data.get('enable_rollback')),
- 'parameters': dict(params_list),
- 'files': json.loads(data.get('parameters')).get('files'),
- 'template': json.loads(data.get('parameters')).get('template')
- }
- if data.get('password'):
- fields['password'] = data.get('password')
-
- if data.get('environment_data'):
- fields['environment'] = data.get('environment_data')
-
- try:
- api.heat.stack_create(self.request, **fields)
- messages.info(request, _("Stack creation started."))
- return True
- except Exception:
- exceptions.handle(request)
-
- def _populate_custom_choices(self, custom_type):
- if custom_type == 'neutron.network':
- return instance_utils.network_field_data(self.request, True)
- if custom_type == 'nova.keypair':
- return instance_utils.keypair_field_data(self.request, True)
- if custom_type == 'glance.image':
- return image_utils.image_field_data(self.request, True)
- if custom_type == 'nova.flavor':
- return instance_utils.flavor_field_data(self.request, True)
- return []
-
-
-class EditStackForm(CreateStackForm):
-
- class Meta(object):
- name = _('Update Stack Parameters')
-
- stack_id = forms.CharField(
- label=_('Stack ID'),
- widget=forms.widgets.HiddenInput)
- stack_name = forms.CharField(
- label=_('Stack Name'),
- widget=forms.TextInput(attrs={'readonly': 'readonly'}))
-
- @sensitive_variables('password')
- def handle(self, request, data):
- prefix_length = len(self.param_prefix)
- params_list = [(k[prefix_length:], v) for (k, v) in data.items()
- if k.startswith(self.param_prefix)]
-
- stack_id = data.get('stack_id')
- fields = {
- 'stack_name': data.get('stack_name'),
- 'timeout_mins': data.get('timeout_mins'),
- 'disable_rollback': not(data.get('enable_rollback')),
- 'parameters': dict(params_list),
- 'files': json.loads(data.get('parameters')).get('files'),
- 'template': json.loads(data.get('parameters')).get('template')
- }
- if data.get('password'):
- fields['password'] = data.get('password')
-
- if data.get('environment_data'):
- fields['environment'] = data.get('environment_data')
-
- try:
- api.heat.stack_update(self.request, stack_id=stack_id, **fields)
- messages.info(request, _("Stack update started."))
- return True
- except Exception:
- exceptions.handle(request)
-
-
-class PreviewStackForm(CreateStackForm):
-
- class Meta(object):
- name = _('Preview Stack Parameters')
-
- def __init__(self, *args, **kwargs):
- self.next_view = kwargs.pop('next_view')
- super(CreateStackForm, self).__init__(*args, **kwargs)
-
- def handle(self, request, data):
- prefix_length = len(self.param_prefix)
- params_list = [(k[prefix_length:], v) for (k, v) in data.items()
- if k.startswith(self.param_prefix)]
- fields = {
- 'stack_name': data.get('stack_name'),
- 'timeout_mins': data.get('timeout_mins'),
- 'disable_rollback': not(data.get('enable_rollback')),
- 'parameters': dict(params_list),
- 'files': json.loads(data.get('parameters')).get('files'),
- 'template': json.loads(data.get('parameters')).get('template')
- }
-
- if data.get('environment_data'):
- fields['environment'] = data.get('environment_data')
-
- try:
- stack_preview = api.heat.stack_preview(self.request, **fields)
- request.method = 'GET'
- return self.next_view.as_view()(request,
- stack_preview=stack_preview)
- except Exception:
- exceptions.handle(request)
diff --git a/openstack_dashboard/dashboards/project/stacks/mappings.py b/openstack_dashboard/dashboards/project/stacks/mappings.py
deleted file mode 100644
index eeab18cffa..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/mappings.py
+++ /dev/null
@@ -1,350 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import json
-import logging
-
-from django.conf import settings
-from django.core.urlresolvers import reverse
-from django.template.defaultfilters import register
-from django.utils import html
-from django.utils import safestring
-import six
-import six.moves.urllib.parse as urlparse
-
-from openstack_dashboard.api import swift
-
-LOG = logging.getLogger(__name__)
-
-
-resource_urls = {
- "AWS::AutoScaling::AutoScalingGroup": {
- 'link': 'horizon:project:stacks:detail'},
- "AWS::CloudFormation::Stack": {
- 'link': 'horizon:project:stacks:detail'},
- "AWS::EC2::Instance": {
- 'link': 'horizon:project:instances:detail'},
- "AWS::EC2::InternetGateway": {
- 'link': 'horizon:project:networks:ports:detail'},
- "AWS::EC2::NetworkInterface": {
- 'link': 'horizon:project:networks:ports:detail'},
- "AWS::EC2::RouteTable": {
- 'link': 'horizon:project:routers:detail'},
- "AWS::EC2::SecurityGroup": {
- 'link': 'horizon:project:security_groups:index'},
- "AWS::EC2::Subnet": {
- 'link': 'horizon:project:networks:subnets:detail'},
- "AWS::EC2::Volume": {
- 'link': 'horizon:project:volumes:detail'},
- "AWS::EC2::VPC": {
- 'link': 'horizon:project:networks:detail'},
- "AWS::S3::Bucket": {
- 'link': 'horizon:project:containers:index'},
- "OS::Cinder::Volume": {
- 'link': 'horizon:project:volumes:detail'},
- "OS::Heat::AccessPolicy": {
- 'link': 'horizon:project:stacks:detail'},
- "OS::Heat::AutoScalingGroup": {
- 'link': 'horizon:project:stacks:detail'},
- "OS::Heat::CloudConfig": {
- 'link': 'horizon:project:stacks:detail'},
- "OS::Neutron::Firewall": {
- 'link': 'horizon:project:firewalls:firewalldetails'},
- "OS::Neutron::FirewallPolicy": {
- 'link': 'horizon:project:firewalls:policydetails'},
- "OS::Neutron::FirewallRule": {
- 'link': 'horizon:project:firewalls:ruledetails'},
- "OS::Heat::HARestarter": {
- 'link': 'horizon:project:stacks:detail'},
- "OS::Heat::InstanceGroup": {
- 'link': 'horizon:project:stacks:detail'},
- "OS::Heat::MultipartMime": {
- 'link': 'horizon:project:stacks:detail'},
- "OS::Heat::ResourceGroup": {
- 'link': 'horizon:project:stacks:detail'},
- "OS::Heat::SoftwareConfig": {
- 'link': 'horizon:project:stacks:detail'},
- "OS::Heat::StructuredConfig": {
- 'link': 'horizon:project:stacks:detail'},
- "OS::Heat::StructuredDeployment": {
- 'link': 'horizon:project:stacks:detail'},
- "OS::Heat::Stack": {
- 'link': 'horizon:project:stacks:detail'},
- "OS::Heat::WaitCondition": {
- 'link': 'horizon:project:stacks:detail'},
- "OS::Heat::WaitConditionHandle": {
- 'link': 'horizon:project:stacks:detail'},
- "OS::Neutron::IKEPolicy": {
- 'link': 'horizon:project:vpn:ikepolicydetails'},
- "OS::Neutron::IPsecPolicy": {
- 'link': 'horizon:project:vpn:ipsecpolicydetails'},
- "OS::Neutron::IPsecSiteConnection": {
- 'link': 'horizon:project:vpn:ipsecsiteconnectiondetails'},
- "OS::Neutron::Net": {
- 'link': 'horizon:project:networks:detail'},
- "OS::Neutron::Port": {
- 'link': 'horizon:project:networks:ports:detail'},
- "OS::Neutron::Router": {
- 'link': 'horizon:project:routers:detail'},
- "OS::Neutron::Subnet": {
- 'link': 'horizon:project:networks:subnets:detail'},
- "OS::Neutron::VPNService": {
- 'link': 'horizon:project:vpn:vpnservicedetails'},
- "OS::Nova::KeyPair": {
- 'link': 'horizon:project:key_pairs:index'},
- "OS::Nova::Server": {
- 'link': 'horizon:project:instances:detail'},
- "OS::Swift::Container": {
- 'link': 'horizon:project:containers:index',
- 'format_pattern': '%s' + swift.FOLDER_DELIMITER},
-}
-
-
-def resource_to_url(resource):
- if (not resource or
- not resource.physical_resource_id or
- not hasattr(resource, 'resource_type')):
- return None
-
- mapping = resource_urls.get(resource.resource_type, {})
- try:
- if 'link' not in mapping:
- return None
- format_pattern = mapping.get('format_pattern') or '%s'
- rid = format_pattern % resource.physical_resource_id
- url = reverse(mapping['link'], args=(rid,))
- except Exception as e:
- LOG.exception(e)
- return None
- return url
-
-
-@register.filter
-def stack_output(output):
- if not output:
- return u''
- if isinstance(output, six.string_types):
- parts = urlparse.urlsplit(output)
- if parts.netloc and parts.scheme in ('http', 'https'):
- url = html.escape(output)
- safe_link = u'%s ' % (url, url)
- return safestring.mark_safe(safe_link)
- if isinstance(output, dict) or isinstance(output, list):
- output = json.dumps(output, indent=2)
- return safestring.mark_safe(u'
%s ' % html.escape(output))
-
-static_url = getattr(settings, "STATIC_URL", "/static/")
-resource_images = {
- 'LB_FAILED': static_url + 'dashboard/img/lb-red.svg',
- 'LB_DELETE': static_url + 'dashboard/img/lb-red.svg',
- 'LB_IN_PROGRESS': static_url + 'dashboard/img/lb-gray.gif',
- 'LB_INIT': static_url + 'dashboard/img/lb-gray.svg',
- 'LB_COMPLETE': static_url + 'dashboard/img/lb-green.svg',
- 'DB_FAILED': static_url + 'dashboard/img/db-red.svg',
- 'DB_DELETE': static_url + 'dashboard/img/db-red.svg',
- 'DB_IN_PROGRESS': static_url + 'dashboard/img/db-gray.gif',
- 'DB_INIT': static_url + 'dashboard/img/db-gray.svg',
- 'DB_COMPLETE': static_url + 'dashboard/img/db-green.svg',
- 'STACK_FAILED': static_url + 'dashboard/img/stack-red.svg',
- 'STACK_DELETE': static_url + 'dashboard/img/stack-red.svg',
- 'STACK_IN_PROGRESS': static_url + 'dashboard/img/stack-gray.gif',
- 'STACK_INIT': static_url + 'dashboard/img/stack-gray.svg',
- 'STACK_COMPLETE': static_url + 'dashboard/img/stack-green.svg',
- 'SERVER_FAILED': static_url + 'dashboard/img/server-red.svg',
- 'SERVER_DELETE': static_url + 'dashboard/img/server-red.svg',
- 'SERVER_IN_PROGRESS': static_url + 'dashboard/img/server-gray.gif',
- 'SERVER_INIT': static_url + 'dashboard/img/server-gray.svg',
- 'SERVER_COMPLETE': static_url + 'dashboard/img/server-green.svg',
- 'ALARM_FAILED': static_url + 'dashboard/img/alarm-red.svg',
- 'ALARM_DELETE': static_url + 'dashboard/img/alarm-red.svg',
- 'ALARM_IN_PROGRESS': static_url + 'dashboard/img/alarm-gray.gif',
- 'ALARM_INIT': static_url + 'dashboard/img/alarm-gray.svg',
- 'ALARM_COMPLETE': static_url + 'dashboard/img/alarm-green.svg',
- 'VOLUME_FAILED': static_url + 'dashboard/img/volume-red.svg',
- 'VOLUME_DELETE': static_url + 'dashboard/img/volume-red.svg',
- 'VOLUME_IN_PROGRESS': static_url + 'dashboard/img/volume-gray.gif',
- 'VOLUME_INIT': static_url + 'dashboard/img/volume-gray.svg',
- 'VOLUME_COMPLETE': static_url + 'dashboard/img/volume-green.svg',
- 'IMAGE_FAILED': static_url + 'dashboard/img/image-red.svg',
- 'IMAGE_DELETE': static_url + 'dashboard/img/image-red.svg',
- 'IMAGE_IN_PROGRESS': static_url + 'dashboard/img/image-gray.gif',
- 'IMAGE_INIT': static_url + 'dashboard/img/image-gray.svg',
- 'IMAGE_COMPLETE': static_url + 'dashboard/img/image-green.svg',
- 'WAIT_FAILED': static_url + 'dashboard/img/wait-red.svg',
- 'WAIT_DELETE': static_url + 'dashboard/img/wait-red.svg',
- 'WAIT_IN_PROGRESS': static_url + 'dashboard/img/wait-gray.gif',
- 'WAIT_INIT': static_url + 'dashboard/img/wait-gray.svg',
- 'WAIT_COMPLETE': static_url + 'dashboard/img/wait-green.svg',
- 'FIREWALL_FAILED': static_url + 'dashboard/img/firewall-red.svg',
- 'FIREWALL_DELETE': static_url + 'dashboard/img/firewall-red.svg',
- 'FIREWALL_IN_PROGRESS': static_url + 'dashboard/img/firewall-gray.gif',
- 'FIREWALL_INIT': static_url + 'dashboard/img/firewall-gray.svg',
- 'FIREWALL_COMPLETE': static_url + 'dashboard/img/firewall-green.svg',
- 'FLOATINGIP_FAILED': static_url + 'dashboard/img/floatingip-red.svg',
- 'FLOATINGIP_DELETE': static_url + 'dashboard/img/floatingip-red.svg',
- 'FLOATINGIP_IN_PROGRESS': static_url + 'dashboard/img/floatingip-gray.gif',
- 'FLOATINGIP_INIT': static_url + 'dashboard/img/floatingip-gray.svg',
- 'FLOATINGIP_COMPLETE': static_url + 'dashboard/img/floatingip-green.svg',
- 'ROUTER_FAILED': static_url + 'dashboard/img/router-red.svg',
- 'ROUTER_DELETE': static_url + 'dashboard/img/router-red.svg',
- 'ROUTER_IN_PROGRESS': static_url + 'dashboard/img/router-gray.gif',
- 'ROUTER_INIT': static_url + 'dashboard/img/router-gray.svg',
- 'ROUTER_COMPLETE': static_url + 'dashboard/img/router-green.svg',
- 'POLICY_FAILED': static_url + 'dashboard/img/policy-red.svg',
- 'POLICY_DELETE': static_url + 'dashboard/img/policy-red.svg',
- 'POLICY_IN_PROGRESS': static_url + 'dashboard/img/policy-gray.gif',
- 'POLICY_INIT': static_url + 'dashboard/img/policy-gray.svg',
- 'POLICY_COMPLETE': static_url + 'dashboard/img/policy-green.svg',
- 'CONFIG_FAILED': static_url + 'dashboard/img/config-red.svg',
- 'CONFIG_DELETE': static_url + 'dashboard/img/config-red.svg',
- 'CONFIG_IN_PROGRESS': static_url + 'dashboard/img/config-gray.gif',
- 'CONFIG_INIT': static_url + 'dashboard/img/config-gray.svg',
- 'CONFIG_COMPLETE': static_url + 'dashboard/img/config-green.svg',
- 'NETWORK_FAILED': static_url + 'dashboard/img/network-red.svg',
- 'NETWORK_DELETE': static_url + 'dashboard/img/network-red.svg',
- 'NETWORK_IN_PROGRESS': static_url + 'dashboard/img/network-gray.gif',
- 'NETWORK_INIT': static_url + 'dashboard/img/network-gray.svg',
- 'NETWORK_COMPLETE': static_url + 'dashboard/img/network-green.svg',
- 'PORT_FAILED': static_url + 'dashboard/img/port-red.svg',
- 'PORT_DELETE': static_url + 'dashboard/img/port-red.svg',
- 'PORT_IN_PROGRESS': static_url + 'dashboard/img/port-gray.gif',
- 'PORT_INIT': static_url + 'dashboard/img/port-gray.svg',
- 'PORT_COMPLETE': static_url + 'dashboard/img/port-green.svg',
- 'SECURITYGROUP_FAILED': static_url + 'dashboard/img/securitygroup-red.svg',
- 'SECURITYGROUP_DELETE': static_url + 'dashboard/img/securitygroup-red.svg',
- 'SECURITYGROUP_IN_PROGRESS':
- static_url + 'dashboard/img/securitygroup-gray.gif',
- 'SECURITYGROUP_INIT': static_url + 'dashboard/img/securitygroup-gray.svg',
- 'SECURITYGROUP_COMPLETE':
- static_url + 'dashboard/img/securitygroup-green.svg',
- 'VPN_FAILED': static_url + 'dashboard/img/vpn-red.svg',
- 'VPN_DELETE': static_url + 'dashboard/img/vpn-red.svg',
- 'VPN_IN_PROGRESS': static_url + 'dashboard/img/vpn-gray.gif',
- 'VPN_INIT': static_url + 'dashboard/img/vpn-gray.svg',
- 'VPN_COMPLETE': static_url + 'dashboard/img/vpn-green.svg',
- 'FLAVOR_FAILED': static_url + 'dashboard/img/flavor-red.svg',
- 'FLAVOR_DELETE': static_url + 'dashboard/img/flavor-red.svg',
- 'FLAVOR_IN_PROGRESS': static_url + 'dashboard/img/flavor-gray.gif',
- 'FLAVOR_INIT': static_url + 'dashboard/img/flavor-gray.svg',
- 'FLAVOR_COMPLETE': static_url + 'dashboard/img/flavor-green.svg',
- 'KEYPAIR_FAILED': static_url + 'dashboard/img/keypair-red.svg',
- 'KEYPAIR_DELETE': static_url + 'dashboard/img/keypair-red.svg',
- 'KEYPAIR_IN_PROGRESS': static_url + 'dashboard/img/keypair-gray.gif',
- 'KEYPAIR_INIT': static_url + 'dashboard/img/keypair-gray.svg',
- 'KEYPAIR_COMPLETE': static_url + 'dashboard/img/keypair-green.svg',
- 'UNKNOWN_FAILED': static_url + 'dashboard/img/unknown-red.svg',
- 'UNKNOWN_DELETE': static_url + 'dashboard/img/unknown-red.svg',
- 'UNKNOWN_IN_PROGRESS': static_url + 'dashboard/img/unknown-gray.gif',
- 'UNKNOWN_INIT': static_url + 'dashboard/img/unknown-gray.svg',
- 'UNKNOWN_COMPLETE': static_url + 'dashboard/img/unknown-green.svg',
-}
-
-
-resource_types = {
- # LB
- 'LoadBalance': 'LB',
- 'HealthMonitor': 'LB',
- 'PoolMember': 'LB',
- 'Pool': 'LB',
- # DB
- 'DBInstance': 'DB',
- 'Database': 'DB',
- # SERVER
- 'Instance': 'SERVER',
- 'Server': 'SERVER',
- # ALARM
- 'Alarm': 'ALARM',
- 'CombinationAlarm': 'ALARM',
- 'CWLiteAlarm': 'ALARM',
- # VOLUME
- 'Volume': 'VOLUME',
- 'VolumeAttachment': 'VOLUME',
- # STACK
- 'stack': 'STACK',
- 'AutoScalingGroup': 'STACK',
- 'InstanceGroup': 'STACK',
- 'ServerGroup': 'STACK',
- 'ResourceGroup': 'STACK',
- # IMAGE
- 'Image': 'IMAGE',
- # WAIT
- 'WaitCondition': 'WAIT',
- 'WaitConditionHandle': 'WAIT',
- 'UpdateWaitConditionHandle': 'WAIT',
- # FIREWALL
- 'Firewall': 'FIREWALL',
- 'FirewallPolicy': 'FIREWALL',
- 'FirewallRule': 'FIREWALL',
- # FLOATINGIP
- 'FloatingIP': 'FLOATINGIP',
- 'FloatingIPAssociation': 'FLOATINGIP',
- # ROUTER
- 'Router': 'ROUTER',
- 'RouterGateway': 'ROUTER',
- 'RouterInterface': 'ROUTER',
- # POLICY
- 'ScalingPolicy': 'POLICY',
- # CONFIG
- 'CloudConfig': 'CONFIG',
- 'MultipartMime': 'CONFIG',
- 'SoftwareConfig': 'CONFIG',
- 'SoftwareDeployment': 'CONFIG',
- 'StructuredConfig': 'CONFIG',
- 'StructuredDeployment': 'CONFIG',
- # NETWORK
- 'Net': 'NETWORK',
- 'Subnet': 'NETWORK',
- 'NetworkGateway': 'NETWORK',
- 'ProviderNet': 'NETWORK',
- # PORT
- 'Port': 'PORT',
- # SECURITYGROUP
- 'SecurityGroup': 'SECURITYGROUP',
- # VPN
- 'VPNService': 'VPN',
- # FLAVOR
- 'Flavor': 'FLAVOR',
- # KEYPAIR
- 'KeyPair': 'KEYPAIR',
-}
-
-
-def get_resource_type(type):
- for key, value in resource_types.items():
- if key in type:
- return value
-
- return 'UNKNOWN'
-
-
-def get_resource_status(status):
- if ('IN_PROGRESS' in status):
- return 'IN_PROGRESS'
- elif ('FAILED' in status):
- return 'FAILED'
- elif ('DELETE' in status):
- return 'DELETE'
- elif ('INIT' in status):
- return 'INIT'
- else:
- return 'COMPLETE'
-
-
-def get_resource_image(status, type):
- """Sets the image url and in_progress action sw based on status."""
- resource_type = get_resource_type(type)
- resource_status = get_resource_status(status)
- resource_state = resource_type + "_" + resource_status
-
- for key in resource_images:
- if key == resource_state:
- return resource_images.get(key)
diff --git a/openstack_dashboard/dashboards/project/stacks/panel.py b/openstack_dashboard/dashboards/project/stacks/panel.py
deleted file mode 100644
index f9e8800381..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/panel.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from django.utils.translation import ugettext_lazy as _
-
-import horizon
-
-
-class Stacks(horizon.Panel):
- name = _("Stacks")
- slug = "stacks"
- permissions = ('openstack.services.orchestration',)
diff --git a/openstack_dashboard/dashboards/project/stacks/resource_types/__init__.py b/openstack_dashboard/dashboards/project/stacks/resource_types/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/openstack_dashboard/dashboards/project/stacks/resource_types/panel.py b/openstack_dashboard/dashboards/project/stacks/resource_types/panel.py
deleted file mode 100644
index b1f37443fc..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/resource_types/panel.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from django.utils.translation import ugettext_lazy as _
-
-import horizon
-
-
-class ResourceTypes(horizon.Panel):
- name = _("Resource Types")
- slug = "stacks.resource_types"
- permissions = ('openstack.services.orchestration',)
- policy_rules = (("orchestration", "stacks:list_resource_types"),)
diff --git a/openstack_dashboard/dashboards/project/stacks/resource_types/tables.py b/openstack_dashboard/dashboards/project/stacks/resource_types/tables.py
deleted file mode 100644
index 66e7702ab1..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/resource_types/tables.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from django.utils.translation import ugettext_lazy as _
-
-from horizon import tables
-
-
-class ResourceTypesFilterAction(tables.FilterAction):
- filter_type = 'server'
- filter_choices = (('name', _('Type ='), True, _("Case sensitive")),)
-
-
-class ResourceTypesTable(tables.DataTable):
- name = tables.Column("resource_type",
- verbose_name=_("Type"),
- link="horizon:project:stacks.resource_types:details",)
-
- def get_object_id(self, resource):
- return resource.resource_type
-
- class Meta(object):
- name = "resource_types"
- verbose_name = _("Resource Types")
- table_actions = (ResourceTypesFilterAction,)
- multi_select = False
diff --git a/openstack_dashboard/dashboards/project/stacks/resource_types/tabs.py b/openstack_dashboard/dashboards/project/stacks/resource_types/tabs.py
deleted file mode 100644
index b0d5467e30..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/resource_types/tabs.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from django.utils.translation import ugettext_lazy as _
-
-from horizon import tabs
-
-
-class ResourceTypeOverviewTab(tabs.Tab):
- name = _("Overview")
- slug = "resource_type_overview"
- template_name = "project/stacks.resource_types/_details.html"
-
- def get_context_data(self, request):
- return {"r_type": self.tab_group.kwargs['rt'],
- "r_type_attributes": self.tab_group.kwargs['rt_attributes'],
- "r_type_properties": self.tab_group.kwargs['rt_properties']}
-
-
-class ResourceTypeDetailsTabs(tabs.TabGroup):
- slug = "resource_type_details"
- tabs = (ResourceTypeOverviewTab,)
diff --git a/openstack_dashboard/dashboards/project/stacks/resource_types/templates/stacks.resource_types/_details.html b/openstack_dashboard/dashboards/project/stacks/resource_types/templates/stacks.resource_types/_details.html
deleted file mode 100644
index 704787e13b..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/resource_types/templates/stacks.resource_types/_details.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{% load i18n %}
-
-
-
- {{ r_type }}
-
-
-
{% trans "Attributes" %}
-
{{ r_type_attributes }}
-
-
-
{% trans "Properties" %}
-
{{ r_type_properties }}
-
-
diff --git a/openstack_dashboard/dashboards/project/stacks/resource_types/tests.py b/openstack_dashboard/dashboards/project/stacks/resource_types/tests.py
deleted file mode 100644
index 4c73644beb..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/resource_types/tests.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from django.core.urlresolvers import reverse
-from django import http
-
-from mox3.mox import IsA
-
-from openstack_dashboard import api
-from openstack_dashboard.test import helpers as test
-
-
-class ResourceTypesTests(test.TestCase):
-
- @test.create_stubs({api.heat: ('resource_types_list',)})
- def test_index(self):
- filters = {}
- api.heat.resource_types_list(
- IsA(http.HttpRequest), filters=filters).AndReturn(
- self.resource_types.list())
- self.mox.ReplayAll()
-
- res = self.client.get(
- reverse('horizon:project:stacks.resource_types:index'))
- self.assertTemplateUsed(
- res, 'horizon/common/_data_table_view.html')
- self.assertContains(res, 'AWS::CloudFormation::Stack')
-
- @test.create_stubs({api.heat: ('resource_type_get',)})
- def test_detail_view(self):
- rt = self.api_resource_types.first()
-
- api.heat.resource_type_get(
- IsA(http.HttpRequest), rt['resource_type']).AndReturn(rt)
- self.mox.ReplayAll()
-
- url = reverse('horizon:project:stacks.resource_types:details',
- args=[rt['resource_type']])
- res = self.client.get(url)
-
- self.assertTemplateUsed(res, 'horizon/common/_detail.html')
- self.assertNoMessages()
diff --git a/openstack_dashboard/dashboards/project/stacks/resource_types/urls.py b/openstack_dashboard/dashboards/project/stacks/resource_types/urls.py
deleted file mode 100644
index 8ab8cb0bda..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/resource_types/urls.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from django.conf.urls import url
-
-from openstack_dashboard.dashboards.project.stacks.resource_types import views
-
-urlpatterns = [
- url(r'^$', views.ResourceTypesView.as_view(), name='index'),
- url(r'^(?P[^/]+)/$',
- views.DetailView.as_view(), name='details'),
-]
diff --git a/openstack_dashboard/dashboards/project/stacks/resource_types/views.py b/openstack_dashboard/dashboards/project/stacks/resource_types/views.py
deleted file mode 100644
index 8afcdf830d..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/resource_types/views.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import yaml
-
-from django.core.urlresolvers import reverse
-from django.utils.translation import ugettext_lazy as _
-
-from horizon import exceptions
-from horizon import tables
-from horizon import tabs
-
-from openstack_dashboard import api
-import openstack_dashboard.dashboards.project.stacks.resource_types.tables \
- as project_tables
-import openstack_dashboard.dashboards.project.stacks.resource_types.tabs \
- as project_tabs
-
-
-class ResourceTypesView(tables.DataTableView):
- table_class = project_tables.ResourceTypesTable
- page_title = _("Resource Types")
-
- def get_data(self):
- try:
- filters = self.get_filters()
- if 'name' in filters:
- filters['name'] = '.*' + filters['name']
- r_types = sorted(api.heat.resource_types_list(self.request,
- filters=filters),
- key=lambda resource: resource.resource_type)
- except Exception:
- r_types = []
- msg = _('Unable to retrieve stack resource types.')
- exceptions.handle(self.request, msg)
- return r_types
-
-
-class DetailView(tabs.TabView):
- tab_group_class = project_tabs.ResourceTypeDetailsTabs
- template_name = 'horizon/common/_detail.html'
- page_title = "{{ resource_type }}"
-
- def get_resource_type(self, request, **kwargs):
- try:
- resource_type_overview = api.heat.resource_type_get(
- request,
- kwargs['resource_type'])
- return resource_type_overview
- except Exception:
- msg = _('Unable to retrieve resource type details.')
- exceptions.handle(request, msg, redirect=self.get_redirect_url())
-
- def get_tabs(self, request, **kwargs):
- resource_type_overview = self.get_resource_type(request, **kwargs)
- r_type = resource_type_overview['resource_type']
- r_type_attributes = resource_type_overview['attributes']
- r_type_properties = resource_type_overview['properties']
- return self.tab_group_class(
- request,
- rt=r_type,
- rt_attributes=yaml.safe_dump(r_type_attributes, indent=2),
- rt_properties=yaml.safe_dump(r_type_properties, indent=2),
- **kwargs)
-
- @staticmethod
- def get_redirect_url():
- return reverse('horizon:project:stacks.resources:index')
diff --git a/openstack_dashboard/dashboards/project/stacks/sro.py b/openstack_dashboard/dashboards/project/stacks/sro.py
deleted file mode 100644
index 4250e7ee9e..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/sro.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from django.template.defaultfilters import title
-from django.template.loader import render_to_string
-
-from horizon.utils import filters
-
-
-def stack_info(stack, stack_image):
- stack.stack_status_desc = title(
- filters.replace_underscores(stack.stack_status))
- if stack.stack_status_reason:
- stack.stack_status_reason = title(
- filters.replace_underscores(stack.stack_status_reason)
- )
- context = {}
- context['stack'] = stack
- context['stack_image'] = stack_image
- return render_to_string('project/stacks/_stack_info.html',
- context)
-
-
-def resource_info(resource):
- resource.resource_status_desc = title(
- filters.replace_underscores(resource.resource_status)
- )
- if resource.resource_status_reason:
- resource.resource_status_reason = title(
- filters.replace_underscores(resource.resource_status_reason)
- )
- context = {}
- context['resource'] = resource
- return render_to_string('project/stacks/_resource_info.html',
- context)
diff --git a/openstack_dashboard/dashboards/project/stacks/tables.py b/openstack_dashboard/dashboards/project/stacks/tables.py
deleted file mode 100644
index 96391ab5c5..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/tables.py
+++ /dev/null
@@ -1,413 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from django.core import urlresolvers
-from django.http import Http404
-from django.template.defaultfilters import title
-from django.utils.translation import pgettext_lazy
-from django.utils.translation import ugettext_lazy as _
-from django.utils.translation import ungettext_lazy
-from heatclient import exc
-
-from horizon import exceptions
-from horizon import messages
-from horizon import tables
-from horizon.utils import filters
-
-from openstack_dashboard import api
-from openstack_dashboard.dashboards.project.stacks import mappings
-
-
-class LaunchStack(tables.LinkAction):
- name = "launch"
- verbose_name = _("Launch Stack")
- url = "horizon:project:stacks:select_template"
- classes = ("ajax-modal",)
- icon = "plus"
- policy_rules = (("orchestration", "stacks:validate_template"),
- ("orchestration", "stacks:create"),)
-
-
-class PreviewStack(tables.LinkAction):
- name = "preview"
- verbose_name = _("Preview Stack")
- url = "horizon:project:stacks:preview_template"
- classes = ("ajax-modal",)
- icon = "eye"
- policy_rules = (("orchestration", "stacks:validate_template"),
- ("orchestration", "stacks:preview"),)
-
-
-class CheckStack(tables.BatchAction):
- name = "check"
- verbose_name = _("Check Stack")
- policy_rules = (("orchestration", "actions:action"),)
- icon = "check-square"
-
- @staticmethod
- def action_present(count):
- return ungettext_lazy(
- u"Check Stack",
- u"Check Stacks",
- count
- )
-
- @staticmethod
- def action_past(count):
- return ungettext_lazy(
- u"Checked Stack",
- u"Checked Stacks",
- count
- )
-
- def action(self, request, stack_id):
- api.heat.action_check(request, stack_id)
-
-
-class SuspendStack(tables.BatchAction):
- name = "suspend"
- verbose_name = _("Suspend Stack")
- policy_rules = (("orchestration", "actions:action"),)
- icon = "pause"
-
- @staticmethod
- def action_present(count):
- return ungettext_lazy(
- u"Suspend Stack",
- u"Suspend Stacks",
- count
- )
-
- @staticmethod
- def action_past(count):
- return ungettext_lazy(
- u"Suspended Stack",
- u"Suspended Stacks",
- count
- )
-
- def action(self, request, stack_id):
- try:
- api.heat.action_suspend(request, stack_id)
- except Exception:
- msg = _('Failed to suspend stack.')
- exceptions.handle(request, msg)
-
-
-class ResumeStack(tables.BatchAction):
- name = "resume"
- verbose_name = _("Resume Stack")
- policy_rules = (("orchestration", "actions:action"),)
- icon = "play"
-
- @staticmethod
- def action_present(count):
- return ungettext_lazy(
- u"Resume Stack",
- u"Resume Stacks",
- count
- )
-
- @staticmethod
- def action_past(count):
- return ungettext_lazy(
- u"Resumed Stack",
- u"Resumed Stacks",
- count
- )
-
- def action(self, request, stack_id):
- try:
- api.heat.action_resume(request, stack_id)
- except Exception:
- msg = _('Failed to resume stack.')
- exceptions.handle(request, msg)
-
-
-class ChangeStackTemplate(tables.LinkAction):
- name = "edit"
- verbose_name = _("Change Stack Template")
- url = "horizon:project:stacks:change_template"
- classes = ("ajax-modal",)
- icon = "pencil"
-
- def get_link_url(self, stack):
- return urlresolvers.reverse(self.url, args=[stack.id])
-
-
-class DeleteStack(tables.DeleteAction):
- @staticmethod
- def action_present(count):
- return ungettext_lazy(
- u"Delete Stack",
- u"Delete Stacks",
- count
- )
-
- @staticmethod
- def action_past(count):
- return ungettext_lazy(
- u"Deleted Stack",
- u"Deleted Stacks",
- count
- )
-
- policy_rules = (("orchestration", "stacks:delete"),)
-
- def delete(self, request, stack_id):
- try:
- api.heat.stack_delete(request, stack_id)
- except Exception:
- msg = _('Failed to delete stack.')
- exceptions.handle(request, msg)
-
- def allowed(self, request, stack):
- if stack is not None:
- return stack.stack_status != 'DELETE_COMPLETE'
- return True
-
-
-class StacksUpdateRow(tables.Row):
- ajax = True
-
- def can_be_selected(self, datum):
- return datum.stack_status != 'DELETE_COMPLETE'
-
- def get_data(self, request, stack_id):
- try:
- stack = api.heat.stack_get(request, stack_id)
- if stack.stack_status == 'DELETE_COMPLETE':
- # returning 404 to the ajax call removes the
- # row from the table on the ui
- raise Http404
- return stack
- except Http404:
- raise
- except Exception as e:
- messages.error(request, e)
- raise
-
-
-class StacksFilterAction(tables.FilterAction):
- filter_type = 'server'
- filter_choices = (('name', _('Stack Name ='), True, _('Case-sensitive')),
- ('id', _('Stack ID ='), True),
- ('status', _('Status ='), True))
-
-
-class StacksTable(tables.DataTable):
- STATUS_CHOICES = (
- ("Complete", True),
- ("Failed", False),
- )
- STACK_STATUS_DISPLAY_CHOICES = (
- ("init_in_progress", pgettext_lazy("current status of stack",
- u"Init In Progress")),
- ("init_complete", pgettext_lazy("current status of stack",
- u"Init Complete")),
- ("init_failed", pgettext_lazy("current status of stack",
- u"Init Failed")),
- ("create_in_progress", pgettext_lazy("current status of stack",
- u"Create In Progress")),
- ("create_complete", pgettext_lazy("current status of stack",
- u"Create Complete")),
- ("create_failed", pgettext_lazy("current status of stack",
- u"Create Failed")),
- ("delete_in_progress", pgettext_lazy("current status of stack",
- u"Delete In Progress")),
- ("delete_complete", pgettext_lazy("current status of stack",
- u"Delete Complete")),
- ("delete_failed", pgettext_lazy("current status of stack",
- u"Delete Failed")),
- ("update_in_progress", pgettext_lazy("current status of stack",
- u"Update In Progress")),
- ("update_complete", pgettext_lazy("current status of stack",
- u"Update Complete")),
- ("update_failed", pgettext_lazy("current status of stack",
- u"Update Failed")),
- ("rollback_in_progress", pgettext_lazy("current status of stack",
- u"Rollback In Progress")),
- ("rollback_complete", pgettext_lazy("current status of stack",
- u"Rollback Complete")),
- ("rollback_failed", pgettext_lazy("current status of stack",
- u"Rollback Failed")),
- ("suspend_in_progress", pgettext_lazy("current status of stack",
- u"Suspend In Progress")),
- ("suspend_complete", pgettext_lazy("current status of stack",
- u"Suspend Complete")),
- ("suspend_failed", pgettext_lazy("current status of stack",
- u"Suspend Failed")),
- ("resume_in_progress", pgettext_lazy("current status of stack",
- u"Resume In Progress")),
- ("resume_complete", pgettext_lazy("current status of stack",
- u"Resume Complete")),
- ("resume_failed", pgettext_lazy("current status of stack",
- u"Resume Failed")),
- ("adopt_in_progress", pgettext_lazy("current status of stack",
- u"Adopt In Progress")),
- ("adopt_complete", pgettext_lazy("current status of stack",
- u"Adopt Complete")),
- ("adopt_failed", pgettext_lazy("current status of stack",
- u"Adopt Failed")),
- ("snapshot_in_progress", pgettext_lazy("current status of stack",
- u"Snapshot In Progress")),
- ("snapshot_complete", pgettext_lazy("current status of stack",
- u"Snapshot Complete")),
- ("snapshot_failed", pgettext_lazy("current status of stack",
- u"Snapshot Failed")),
- ("check_in_progress", pgettext_lazy("current status of stack",
- u"Check In Progress")),
- ("check_complete", pgettext_lazy("current status of stack",
- u"Check Complete")),
- ("check_failed", pgettext_lazy("current status of stack",
- u"Check Failed")),
- )
- name = tables.Column("stack_name",
- verbose_name=_("Stack Name"),
- link="horizon:project:stacks:detail",)
- created = tables.Column("creation_time",
- verbose_name=_("Created"),
- filters=(filters.parse_isotime,
- filters.timesince_sortable),
- attrs={'data-type': 'timesince'})
- updated = tables.Column("updated_time",
- verbose_name=_("Updated"),
- filters=(filters.parse_isotime,
- filters.timesince_or_never))
- status = tables.Column("status",
- hidden=True,
- status=True,
- status_choices=STATUS_CHOICES)
-
- stack_status = tables.Column("stack_status",
- verbose_name=_("Status"),
- display_choices=STACK_STATUS_DISPLAY_CHOICES)
-
- def get_object_display(self, stack):
- return stack.stack_name
-
- class Meta(object):
- name = "stacks"
- verbose_name = _("Stacks")
- pagination_param = 'stack_marker'
- status_columns = ["status", ]
- row_class = StacksUpdateRow
- table_actions_menu = (CheckStack,
- SuspendStack,
- ResumeStack,)
- table_actions = (LaunchStack,
- PreviewStack,
- DeleteStack,
- StacksFilterAction,)
- row_actions = (CheckStack,
- SuspendStack,
- ResumeStack,
- ChangeStackTemplate,
- DeleteStack,)
-
-
-def get_resource_url(obj):
- if obj.physical_resource_id == obj.stack_id:
- return None
- return urlresolvers.reverse('horizon:project:stacks:resource',
- args=(obj.stack_id, obj.resource_name))
-
-
-class EventsTable(tables.DataTable):
-
- logical_resource = tables.Column('resource_name',
- verbose_name=_("Stack Resource"),
- link=get_resource_url)
- physical_resource = tables.Column('physical_resource_id',
- verbose_name=_("Resource"))
- timestamp = tables.Column('event_time',
- verbose_name=_("Time Since Event"),
- filters=(filters.parse_isotime,
- filters.timesince_or_never))
- status = tables.Column("resource_status",
- filters=(title, filters.replace_underscores),
- verbose_name=_("Status"),)
-
- statusreason = tables.Column("resource_status_reason",
- verbose_name=_("Status Reason"),)
-
- class Meta(object):
- name = "events"
- verbose_name = _("Stack Events")
-
-
-class ResourcesUpdateRow(tables.Row):
- ajax = True
-
- def get_data(self, request, resource_name):
- try:
- stack = self.table.stack
- stack_identifier = '%s/%s' % (stack.stack_name, stack.id)
- return api.heat.resource_get(
- request, stack_identifier, resource_name)
- except exc.HTTPNotFound:
- # returning 404 to the ajax call removes the
- # row from the table on the ui
- raise Http404
- except Exception as e:
- messages.error(request, e)
-
-
-class ResourcesTable(tables.DataTable):
- class StatusColumn(tables.Column):
- def get_raw_data(self, datum):
- return datum.resource_status.partition("_")[2]
-
- STATUS_CHOICES = (
- ("Complete", True),
- ("Failed", False),
- )
- STATUS_DISPLAY_CHOICES = StacksTable.STACK_STATUS_DISPLAY_CHOICES
-
- logical_resource = tables.Column('resource_name',
- verbose_name=_("Stack Resource"),
- link=get_resource_url)
- physical_resource = tables.Column('physical_resource_id',
- verbose_name=_("Resource"),
- link=mappings.resource_to_url)
- resource_type = tables.Column("resource_type",
- verbose_name=_("Stack Resource Type"),)
- updated_time = tables.Column('updated_time',
- verbose_name=_("Date Updated"),
- filters=(filters.parse_isotime,
- filters.timesince_or_never))
- status = tables.Column("resource_status",
- verbose_name=_("Status"),
- display_choices=STATUS_DISPLAY_CHOICES)
-
- statusreason = tables.Column("resource_status_reason",
- verbose_name=_("Status Reason"),)
-
- status_hidden = StatusColumn("status",
- hidden=True,
- status=True,
- status_choices=STATUS_CHOICES)
-
- def __init__(self, request, data=None,
- needs_form_wrapper=None, **kwargs):
- super(ResourcesTable, self).__init__(
- request, data, needs_form_wrapper, **kwargs)
- self.stack = kwargs['stack']
-
- def get_object_id(self, datum):
- return datum.resource_name
-
- class Meta(object):
- name = "resources"
- verbose_name = _("Stack Resources")
- status_columns = ["status_hidden", ]
- row_class = ResourcesUpdateRow
diff --git a/openstack_dashboard/dashboards/project/stacks/tabs.py b/openstack_dashboard/dashboards/project/stacks/tabs.py
deleted file mode 100644
index 1e6c92be1f..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/tabs.py
+++ /dev/null
@@ -1,173 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import logging
-
-from django.utils.translation import ugettext_lazy as _
-
-from horizon import messages
-from horizon import tabs
-from openstack_dashboard import api
-from openstack_dashboard import policy
-
-from openstack_dashboard.dashboards.project.stacks \
- import api as project_api
-from openstack_dashboard.dashboards.project.stacks import mappings
-from openstack_dashboard.dashboards.project.stacks \
- import tables as project_tables
-
-
-LOG = logging.getLogger(__name__)
-
-
-class StackTopologyTab(tabs.Tab):
- name = _("Topology")
- slug = "topology"
- template_name = "project/stacks/_detail_topology.html"
- preload = False
-
- def allowed(self, request):
- return policy.check(
- (("orchestration", "stacks:template"),
- ("orchestration", "stacks:lookup"),
- ("orchestration", "stacks:show"),
- ("orchestration", "resource:index"),),
- request)
-
- def get_context_data(self, request):
- context = {}
- stack = self.tab_group.kwargs['stack']
- context['stack_id'] = stack.id
- context['d3_data'] = project_api.d3_data(request, stack_id=stack.id)
- return context
-
-
-class StackOverviewTab(tabs.Tab):
- name = _("Overview")
- slug = "overview"
- template_name = "project/stacks/_detail_overview.html"
-
- def allowed(self, request):
- return policy.check(
- (("orchestration", "stacks:template"),
- ("orchestration", "stacks:lookup"),
- ("orchestration", "stacks:show"),),
- request)
-
- def get_context_data(self, request):
- return {"stack": self.tab_group.kwargs['stack']}
-
-
-class ResourceOverviewTab(tabs.Tab):
- name = _("Overview")
- slug = "resource_overview"
- template_name = "project/stacks/_resource_overview.html"
-
- def get_context_data(self, request):
- resource = self.tab_group.kwargs['resource']
- resource_url = mappings.resource_to_url(resource)
- return {
- "resource": resource,
- "resource_url": resource_url,
- "metadata": self.tab_group.kwargs['metadata']}
-
-
-class StackEventsTab(tabs.Tab):
- name = _("Events")
- slug = "events"
- template_name = "project/stacks/_detail_events.html"
- preload = False
-
- def allowed(self, request):
- return policy.check(
- (("orchestration", "stacks:template"),
- ("orchestration", "stacks:lookup"),
- ("orchestration", "stacks:show"),
- ("orchestration", "events:index"),),
- request)
-
- def get_context_data(self, request):
- stack = self.tab_group.kwargs['stack']
- try:
- stack_identifier = '%s/%s' % (stack.stack_name, stack.id)
- events = api.heat.events_list(self.request, stack_identifier)
- LOG.debug('got events %s', events)
- # The stack id is needed to generate the resource URL.
- for event in events:
- event.stack_id = stack.id
- except Exception:
- events = []
- messages.error(request, _(
- 'Unable to get events for stack "%s".') % stack.stack_name)
- return {"stack": stack,
- "table": project_tables.EventsTable(request, data=events), }
-
-
-class StackResourcesTab(tabs.Tab):
- name = _("Resources")
- slug = "resources"
- template_name = "project/stacks/_detail_resources.html"
- preload = False
-
- def allowed(self, request):
- return policy.check(
- (("orchestration", "stacks:template"),
- ("orchestration", "stacks:lookup"),
- ("orchestration", "stacks:show"),
- ("orchestration", "resource:index"),),
- request)
-
- def get_context_data(self, request):
- stack = self.tab_group.kwargs['stack']
- try:
- stack_identifier = '%s/%s' % (stack.stack_name, stack.id)
- resources = api.heat.resources_list(self.request, stack_identifier)
- LOG.debug('got resources %s', resources)
- # The stack id is needed to generate the resource URL.
- for r in resources:
- r.stack_id = stack.id
- except Exception:
- resources = []
- messages.error(request, _(
- 'Unable to get resources for stack "%s".') % stack.stack_name)
- return {"stack": stack,
- "table": project_tables.ResourcesTable(
- request, data=resources, stack=stack), }
-
-
-class StackTemplateTab(tabs.Tab):
- name = _("Template")
- slug = "stack_template"
- template_name = "project/stacks/_stack_template.html"
-
- def allowed(self, request):
- return policy.check(
- (("orchestration", "stacks:template"),
- ("orchestration", "stacks:lookup"),
- ("orchestration", "stacks:show"),),
- request)
-
- def get_context_data(self, request):
- return {"stack_template": self.tab_group.kwargs['stack_template']}
-
-
-class StackDetailTabs(tabs.TabGroup):
- slug = "stack_details"
- tabs = (StackTopologyTab, StackOverviewTab, StackResourcesTab,
- StackEventsTab, StackTemplateTab)
- sticky = True
-
-
-class ResourceDetailTabs(tabs.TabGroup):
- slug = "resource_details"
- tabs = (ResourceOverviewTab,)
- sticky = True
diff --git a/openstack_dashboard/dashboards/project/stacks/template_versions/__init__.py b/openstack_dashboard/dashboards/project/stacks/template_versions/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/openstack_dashboard/dashboards/project/stacks/template_versions/panel.py b/openstack_dashboard/dashboards/project/stacks/template_versions/panel.py
deleted file mode 100644
index 3492d59a27..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/template_versions/panel.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from django.utils.translation import ugettext_lazy as _
-
-import horizon
-
-
-class TemplateVersions(horizon.Panel):
- name = _("Template Versions")
- slug = "stacks.template_versions"
- permissions = ('openstack.services.orchestration',)
- policy_rules = (("orchestration", "stacks:list_template_versions"),)
diff --git a/openstack_dashboard/dashboards/project/stacks/template_versions/tables.py b/openstack_dashboard/dashboards/project/stacks/template_versions/tables.py
deleted file mode 100644
index 8c63d14cb2..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/template_versions/tables.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from django.template import defaultfilters as filters
-from django.utils.translation import ugettext_lazy as _
-
-from horizon import tables
-
-
-class TemplateVersionsTable(tables.DataTable):
- version = tables.Column(
- "version",
- verbose_name=_("Version"),
- link="horizon:project:stacks.template_versions:details",)
- type = tables.Column(
- "type",
- verbose_name=_("Type"),
- filters=(filters.upper,))
-
- def get_object_id(self, template_versions):
- return template_versions.version
-
- class Meta(object):
- name = "template_versions"
- table_actions = (tables.FilterAction,)
- verbose_name = _("Template Versions")
- table_actions = (tables.FilterAction,)
- multi_select = False
-
-
-class TemplateFunctionsTable(tables.DataTable):
- functions = tables.Column('functions', verbose_name=_("Function"))
- description = tables.Column('description', verbose_name=_("Description"))
-
- def get_object_id(self, template_functions):
- return template_functions.functions
-
- class Meta(object):
- name = "template_functions"
- verbose_name = _("Template Functions")
- table_actions = (tables.FilterAction,)
- multi_select = False
diff --git a/openstack_dashboard/dashboards/project/stacks/template_versions/tabs.py b/openstack_dashboard/dashboards/project/stacks/template_versions/tabs.py
deleted file mode 100644
index 9cb90968c3..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/template_versions/tabs.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from django.utils.translation import ugettext_lazy as _
-
-from horizon import messages
-from horizon import tabs
-from openstack_dashboard import api
-from openstack_dashboard import policy
-
-from openstack_dashboard.dashboards.project.stacks.template_versions \
- import tables as project_tables
-
-
-class TemplateFunctionsTab(tabs.Tab):
- name = _("Template Functions")
- slug = "template_functions"
- template_name = "project/stacks.template_versions/_details.html"
- preload = False
-
- def allowed(self, request):
- return policy.check(
- (("orchestration", "stacks:list_template_functions"),),
- request)
-
- def get_context_data(self, request):
- template_version = self.tab_group.kwargs['template_version']
- try:
- template_functions = api.heat.template_function_list(
- self.request, template_version)
- except Exception:
- template_functions = []
- messages.error(request, _('Unable to get functions for template '
- 'version "%s".') % template_version)
- return {"table": project_tables.TemplateFunctionsTable(
- request, data=template_functions), }
-
-
-class TemplateVersionDetailsTabs(tabs.TabGroup):
- slug = "template_version_details"
- tabs = (TemplateFunctionsTab,)
diff --git a/openstack_dashboard/dashboards/project/stacks/template_versions/templates/stacks.template_versions/_details.html b/openstack_dashboard/dashboards/project/stacks/template_versions/templates/stacks.template_versions/_details.html
deleted file mode 100644
index 9976f88dd9..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/template_versions/templates/stacks.template_versions/_details.html
+++ /dev/null
@@ -1,3 +0,0 @@
-{% load i18n %}
-
-{{ table.render }}
diff --git a/openstack_dashboard/dashboards/project/stacks/template_versions/templates/stacks.template_versions/index.html b/openstack_dashboard/dashboards/project/stacks/template_versions/templates/stacks.template_versions/index.html
deleted file mode 100644
index 0a39d4a5e8..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/template_versions/templates/stacks.template_versions/index.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Template Versions" %}{% endblock %}
-
-{% block main %}
- {{ table.render }}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/template_versions/tests.py b/openstack_dashboard/dashboards/project/stacks/template_versions/tests.py
deleted file mode 100644
index fcace15f47..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/template_versions/tests.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from django.core.urlresolvers import reverse
-from django import http
-
-from mox3.mox import IsA
-
-from openstack_dashboard import api
-from openstack_dashboard.test import helpers as test
-
-
-class TemplateVersionsTests(test.TestCase):
- INDEX_URL = reverse('horizon:project:stacks.template_versions:index')
-
- @test.create_stubs({api.heat: ('template_version_list',)})
- def test_index(self):
- api.heat.template_version_list(
- IsA(http.HttpRequest)).AndReturn(self.template_versions.list())
- self.mox.ReplayAll()
-
- res = self.client.get(self.INDEX_URL)
- self.assertTemplateUsed(
- res, 'project/stacks.template_versions/index.html')
- self.assertContains(res, 'HeatTemplateFormatVersion.2012-12-12')
-
- @test.create_stubs({api.heat: ('template_version_list',)})
- def test_index_exception(self):
- api.heat.template_version_list(
- IsA(http.HttpRequest)).AndRaise(self.exceptions.heat)
- self.mox.ReplayAll()
-
- res = self.client.get(self.INDEX_URL)
- self.assertTemplateUsed(
- res, 'project/stacks.template_versions/index.html')
- self.assertEqual(len(res.context['table'].data), 0)
- self.assertMessageCount(res, error=1)
-
- @test.create_stubs({api.heat: ('template_function_list',)})
- def test_detail_view(self):
- t_version = self.template_versions.first().version
- t_functions = self.template_functions.list()
-
- api.heat.template_function_list(
- IsA(http.HttpRequest), t_version).AndReturn(t_functions)
- self.mox.ReplayAll()
-
- url = reverse('horizon:project:stacks.template_versions:details',
- args=[t_version])
- res = self.client.get(url)
-
- self.assertTemplateUsed(res, 'horizon/common/_detail.html')
- self.assertNoMessages()
-
- @test.create_stubs({api.heat: ('template_function_list',)})
- def test_detail_view_with_exception(self):
- t_version = self.template_versions.first().version
-
- api.heat.template_function_list(
- IsA(http.HttpRequest), t_version).AndRaise(self.exceptions.heat)
- self.mox.ReplayAll()
-
- url = reverse('horizon:project:stacks.template_versions:details',
- args=[t_version])
- res = self.client.get(url)
-
- self.assertTemplateUsed(res, 'horizon/common/_detail.html')
- self.assertEqual(len(res.context['table'].data), 0)
- self.assertMessageCount(res, error=1)
diff --git a/openstack_dashboard/dashboards/project/stacks/template_versions/urls.py b/openstack_dashboard/dashboards/project/stacks/template_versions/urls.py
deleted file mode 100644
index 5e2bbc2e58..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/template_versions/urls.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from django.conf.urls import url
-
-from openstack_dashboard.dashboards.project.stacks.template_versions \
- import views
-
-
-urlpatterns = [
- url(r'^$', views.TemplateVersionsView.as_view(), name='index'),
- url(r'^(?P[^/]+)/$',
- views.DetailView.as_view(), name='details'),
-]
diff --git a/openstack_dashboard/dashboards/project/stacks/template_versions/views.py b/openstack_dashboard/dashboards/project/stacks/template_versions/views.py
deleted file mode 100644
index 22eabd77fa..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/template_versions/views.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from django.core.urlresolvers import reverse
-from django.utils.translation import ugettext_lazy as _
-
-from horizon import exceptions
-from horizon import tables
-from horizon import tabs
-
-from openstack_dashboard import api
-import openstack_dashboard.dashboards.project.stacks.template_versions.tables \
- as project_tables
-import openstack_dashboard.dashboards.project.stacks.template_versions.tabs \
- as project_tabs
-
-
-class TemplateVersionsView(tables.DataTableView):
- table_class = project_tables.TemplateVersionsTable
- template_name = 'project/stacks.template_versions/index.html'
- page_title = _("Template Versions")
-
- def get_data(self):
- try:
- template_versions = sorted(
- api.heat.template_version_list(self.request),
- key=lambda template_version: template_version.version)
- except Exception:
- template_versions = []
- msg = _('Unable to retrieve template versions.')
- exceptions.handle(self.request, msg)
- return template_versions
-
-
-class DetailView(tabs.TabView):
- tab_group_class = project_tabs.TemplateVersionDetailsTabs
- template_name = 'horizon/common/_detail.html'
- page_title = "{{ template_version }}"
-
- def get_template_version(self, request, **kwargs):
- try:
- template_functions = api.heat.template_function_list(
- request, kwargs['template_version'])
- return template_functions
- except Exception:
- msg = _('Unable to retrieve template functions.')
- exceptions.handle(request, msg, redirect=self.get_redirect_url())
-
- @staticmethod
- def get_redirect_url():
- return reverse('horizon:project:stacks.template_versions:index')
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_change_template.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_change_template.html
deleted file mode 100644
index bd31f700fd..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_change_template.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends "horizon/common/_modal_form.html" %}
-{% load i18n %}
-{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
-{% block modal-body-right %}
- {% trans "Description:" %}
- {% trans "Use one of the available template source options to specify the template to be used in creating this stack." %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_create.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_create.html
deleted file mode 100644
index 19a3f1b217..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_create.html
+++ /dev/null
@@ -1,6 +0,0 @@
-{% extends "horizon/common/_modal_form.html" %}
-{% load i18n %}
-{% block modal-body-right %}
- {% trans "Description:" %}
- {% trans "Create a new stack with the provided values." %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_events.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_events.html
deleted file mode 100644
index 9976f88dd9..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_events.html
+++ /dev/null
@@ -1,3 +0,0 @@
-{% load i18n %}
-
-{{ table.render }}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_overview.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_overview.html
deleted file mode 100644
index 56534bba3e..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_overview.html
+++ /dev/null
@@ -1,55 +0,0 @@
-{% load i18n sizeformat %}
-
-
-
- {% trans "Name" %}
- {{ stack.stack_name }}
- {% trans "ID" %}
- {{ stack.id }}
- {% trans "Description" %}
- {{ stack.description }}
-
-
-
{% trans "Status" %}
-
-
- {% trans "Created" %}
- {{ stack.creation_time|parse_isotime|timesince_or_never }}
- {% trans "Last Updated" %}
- {{ stack.updated_time|parse_isotime|timesince_or_never }}
- {% trans "Status" %}
-
- {% blocktrans with stack_status_title=stack.stack_status|title stack_status_reason=stack.stack_status_reason %}{{ stack_status_title }}: {{ stack_status_reason }}{% endblocktrans %}
-
-
-
-
{% trans "Outputs" %}
-
-
- {% for output in stack.outputs %}
- {{ output.output_key }}
- {{ output.description }}
-
- {{ output.output_value|stack_output }}
-
- {% endfor %}
-
-
-
{% trans "Stack Parameters" %}
-
-
- {% for key, value in stack.parameters.items %}
- {{ key }}
- {{ value }}
- {% endfor %}
-
-
-
{% trans "Launch Parameters" %}
-
-
- {% trans "Timeout" %}
- {{ stack.timeout_mins }} {% trans "Minutes" %}
- {% trans "Rollback" %}
- {% if stack.disable_rollback %}{% trans "Disabled" %}{% else %}{% trans "Enabled" %}{% endif %}
-
-
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_resources.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_resources.html
deleted file mode 100644
index 9976f88dd9..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_resources.html
+++ /dev/null
@@ -1,3 +0,0 @@
-{% load i18n %}
-
-{{ table.render }}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_topology.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_topology.html
deleted file mode 100644
index d906ceadd9..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_topology.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% load i18n sizeformat %}
-
-
\ No newline at end of file
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview.html
deleted file mode 100644
index 2402478753..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview.html
+++ /dev/null
@@ -1,6 +0,0 @@
-{% extends "horizon/common/_modal_form.html" %}
-{% load i18n %}
-{% block modal-body-right %}
- {% trans "Description:" %}
- {% trans "Preview a new stack with the provided values." %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview_details.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview_details.html
deleted file mode 100644
index 12d131a488..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview_details.html
+++ /dev/null
@@ -1,58 +0,0 @@
-{% extends "horizon/common/_modal.html" %}
-{% load i18n %}
-
-{% block modal-header %}{% trans "Stack Preview" %}{% endblock %}
-
-{% block modal-body %}
-
-{% endblock %}
-
-{% block modal-footer %}
- {% trans "Close" %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview_template.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview_template.html
deleted file mode 100644
index 76f14b0c7f..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_preview_template.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends "horizon/common/_modal_form.html" %}
-{% load i18n %}
-{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
-{% block modal-body-right %}
- {% trans "Description:" %}
- {% trans "Use one of the available template source options to specify the template to be used in previewing this stack." %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_resource_info.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_resource_info.html
deleted file mode 100644
index 989c0127bb..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_resource_info.html
+++ /dev/null
@@ -1,10 +0,0 @@
-{{ resource.resource_name }}
-
-{% if resource.resource_status == 'CREATE_FAILED' %}
-{{ resource.resource_status_desc }}
-{{ resource.resource_status_reason }}
-{% else %}
-{{ resource.resource_status_desc }}
-{% endif %}
-
-{{ resource.resource_type }}
\ No newline at end of file
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_resource_overview.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_resource_overview.html
deleted file mode 100644
index ef1ca25e5d..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_resource_overview.html
+++ /dev/null
@@ -1,38 +0,0 @@
-{% load i18n sizeformat %}
-
-
-
- {% trans "Stack Resource ID" %}
- {{ resource.resource_name }}
- {% trans "Resource ID" %}
-
- {% if resource_url %}
-
- {{ resource.physical_resource_id }}
-
- {% else %}
- {{ resource.physical_resource_id }}
- {% endif %}
-
- {% trans "Stack Resource Type" %}
- {{ resource.resource_type }}
- {% trans "Description" %}
- {{ resource.description }}
-
-
-
{% trans "Status" %}
-
-
- {% trans "Last Updated" %}
- {{ resource.updated_time|parse_isotime|timesince_or_never }}
- {% trans "Status" %}
-
- {% blocktrans with resource_status=resource.resource_status|title|replace_underscores resource_status_reason=resource.resource_status_reason %}{{ resource_status }}: {{ resource_status_reason }}{% endblocktrans %}
-
-
-
-
{% trans "Resource Metadata" %}
-
-
{{ metadata }}
-
-
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_select_template.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_select_template.html
deleted file mode 100644
index bd31f700fd..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_select_template.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends "horizon/common/_modal_form.html" %}
-{% load i18n %}
-{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
-{% block modal-body-right %}
- {% trans "Description:" %}
- {% trans "Use one of the available template source options to specify the template to be used in creating this stack." %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_info.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_info.html
deleted file mode 100644
index 6e657cb3b3..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_info.html
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
{{ stack.stack_name }}
-
{{ stack.stack_status_desc }}
-
-
-{% if stack.stack_status == 'CREATE_FAILED' %}
- {{ stack.stack_status_reason }}
-{% endif %}
-{% for output in stack.outputs %}
- {% if output.output_key == 'WebsiteURL' %}
- {{ output.description }}
- {% endif %}
-{% endfor %}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_template.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_template.html
deleted file mode 100644
index 17eed2085c..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_template.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% load i18n sizeformat %}
-
-
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_update.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_update.html
deleted file mode 100644
index f3b63377c3..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_update.html
+++ /dev/null
@@ -1,6 +0,0 @@
-{% extends "horizon/common/_modal_form.html" %}
-{% load i18n %}
-{% block modal-body-right %}
- {% trans "Description:" %}
- {% trans "Update a stack with the provided values. Please note that any encrypted parameters, such as passwords, will be reset to default if you do not change them here." %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/change_template.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/change_template.html
deleted file mode 100644
index 8bf6bfdf4f..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/change_template.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Change Template" %}{% endblock %}
-
-{% block main %}
- {% include 'project/stacks/_change_template.html' %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/create.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/create.html
deleted file mode 100644
index 7881a96a4a..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/create.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Launch Stack" %}{% endblock %}
-
-{% block main %}
- {% include 'project/stacks/_create.html' %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/preview.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/preview.html
deleted file mode 100644
index ded74a40c2..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/preview.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Preview Stack" %}{% endblock %}
-
-{% block main %}
- {% include 'project/stacks/_preview.html' %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/preview_details.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/preview_details.html
deleted file mode 100644
index 8d86df5405..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/preview_details.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Preview Stack Details" %}{% endblock %}
-
-{% block main %}
- {% include 'project/stacks/_preview_details.html' %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/preview_template.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/preview_template.html
deleted file mode 100644
index e20931cf7f..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/preview_template.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Preview Template" %}{% endblock %}
-
-{% block main %}
- {% include 'project/stacks/_preview_template.html' %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/select_template.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/select_template.html
deleted file mode 100644
index efe0b444f3..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/select_template.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Select Template" %}{% endblock %}
-
-{% block main %}
- {% include 'project/stacks/_select_template.html' %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/update.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/update.html
deleted file mode 100644
index 61b9766fad..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/templates/stacks/update.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'base.html' %}
-{% load i18n %}
-{% block title %}{% trans "Update Stack Parameters" %}{% endblock %}
-
-{% block main %}
- {% include 'project/stacks/_update.html' %}
-{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/stacks/tests.py b/openstack_dashboard/dashboards/project/stacks/tests.py
deleted file mode 100644
index d646a51d15..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/tests.py
+++ /dev/null
@@ -1,1003 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import json
-import re
-
-import django
-from django.conf import settings
-from django.core import exceptions
-from django.core.urlresolvers import reverse
-from django import http
-from django.test.utils import override_settings
-from django.utils import html
-from heatclient.common import template_format as hc_format
-from mox3.mox import IsA
-import six
-
-from openstack_dashboard import api
-from openstack_dashboard.dashboards.project.stacks import api as project_api
-from openstack_dashboard.dashboards.project.stacks import forms
-from openstack_dashboard.dashboards.project.stacks import mappings
-from openstack_dashboard.dashboards.project.stacks import tables
-from openstack_dashboard.test import helpers as test
-
-
-INDEX_TEMPLATE = 'horizon/common/_data_table_view.html'
-INDEX_URL = reverse('horizon:project:stacks:index')
-DETAIL_URL = 'horizon:project:stacks:detail'
-
-
-class MockResource(object):
- def __init__(self, resource_type, physical_resource_id):
- self.resource_type = resource_type
- self.physical_resource_id = physical_resource_id
-
-
-class MappingsTests(test.TestCase):
-
- def test_mappings(self):
-
- def assertMappingUrl(url, resource_type, physical_resource_id):
- mock = MockResource(resource_type, physical_resource_id)
- mock_url = mappings.resource_to_url(mock)
- self.assertEqual(url, mock_url)
-
- assertMappingUrl(
- '/project/networks/subnets/aaa/detail',
- 'OS::Neutron::Subnet',
- 'aaa')
- assertMappingUrl(
- None,
- 'OS::Neutron::Subnet',
- None)
- assertMappingUrl(
- None,
- None,
- None)
- assertMappingUrl(
- None,
- 'AWS::AutoScaling::LaunchConfiguration',
- 'aaa')
- assertMappingUrl(
- '/project/instances/aaa/',
- 'AWS::EC2::Instance',
- 'aaa')
- assertMappingUrl(
- '/project/containers/container/aaa/',
- 'OS::Swift::Container',
- 'aaa')
- assertMappingUrl(
- None,
- 'Foo::Bar::Baz',
- 'aaa')
- assertMappingUrl(
- '/project/instances/aaa/',
- 'OS::Nova::Server',
- 'aaa')
- assertMappingUrl(
- '/project/stacks/stack/aaa/',
- 'OS::Heat::ResourceGroup',
- 'aaa')
-
- def test_stack_output(self):
- self.assertEqual(u'foo ', mappings.stack_output('foo'))
- self.assertEqual(u'', mappings.stack_output(None))
-
- outputs = ['one', 'two', 'three']
- # On Python 3, the pretty JSON output doesn't add space before newline
- if six.PY3:
- expected_text = """[\n "one",\n "two",\n "three"\n]"""
- else:
- expected_text = """[\n "one", \n "two", \n "three"\n]"""
-
- self.assertEqual(u'%s ' % html.escape(expected_text),
- mappings.stack_output(outputs))
-
- outputs = {'foo': 'bar'}
- expected_text = """{\n "foo": "bar"\n}"""
- self.assertEqual(u'%s ' % html.escape(expected_text),
- mappings.stack_output(outputs))
-
- self.assertEqual(
- u''
- 'http://www.example.com/foo ',
- mappings.stack_output('http://www.example.com/foo'))
-
-
-class StackTests(test.TestCase):
-
- @override_settings(API_RESULT_PAGE_SIZE=2)
- @test.create_stubs({api.heat: ('stacks_list',)})
- def test_index_paginated(self):
- stacks = self.stacks.list()[:5]
- filters = {}
- api.heat.stacks_list(IsA(http.HttpRequest),
- marker=None,
- paginate=True,
- sort_dir='desc',
- filters=filters) \
- .AndReturn([stacks, True, True])
- api.heat.stacks_list(IsA(http.HttpRequest),
- marker=None,
- paginate=True,
- sort_dir='desc',
- filters=filters) \
- .AndReturn([stacks[:2], True, True])
- api.heat.stacks_list(IsA(http.HttpRequest),
- marker=stacks[2].id,
- paginate=True,
- sort_dir='desc',
- filters=filters) \
- .AndReturn([stacks[2:4], True, True])
- api.heat.stacks_list(IsA(http.HttpRequest),
- marker=stacks[4].id,
- paginate=True,
- sort_dir='desc',
- filters=filters) \
- .AndReturn([stacks[4:], True, True])
- self.mox.ReplayAll()
-
- url = reverse('horizon:project:stacks:index')
- res = self.client.get(url)
- # get all
- self.assertEqual(len(res.context['stacks_table'].data),
- len(stacks))
- self.assertTemplateUsed(res, INDEX_TEMPLATE)
-
- res = self.client.get(url)
- # get first page with 2 items
- self.assertEqual(len(res.context['stacks_table'].data),
- settings.API_RESULT_PAGE_SIZE)
-
- url = "%s?%s=%s" % (reverse('horizon:project:stacks:index'),
- tables.StacksTable._meta.pagination_param,
- stacks[2].id)
- res = self.client.get(url)
- # get second page (items 2-4)
- self.assertEqual(len(res.context['stacks_table'].data),
- settings.API_RESULT_PAGE_SIZE)
-
- url = "%s?%s=%s" % (reverse('horizon:project:stacks:index'),
- tables.StacksTable._meta.pagination_param,
- stacks[4].id)
- res = self.client.get(url)
- # get third page (item 5)
- self.assertEqual(len(res.context['stacks_table'].data),
- 1)
-
- @override_settings(API_RESULT_PAGE_SIZE=2)
- @test.create_stubs({api.heat: ('stacks_list',)})
- def test_index_prev_paginated(self):
- stacks = self.stacks.list()[:3]
- filters = {}
- api.heat.stacks_list(IsA(http.HttpRequest),
- marker=None,
- paginate=True,
- sort_dir='desc',
- filters=filters) \
- .AndReturn([stacks, True, False])
- api.heat.stacks_list(IsA(http.HttpRequest),
- marker=None,
- paginate=True,
- sort_dir='desc',
- filters=filters) \
- .AndReturn([stacks[:2], True, True])
- api.heat.stacks_list(IsA(http.HttpRequest),
- marker=stacks[2].id,
- paginate=True,
- sort_dir='desc',
- filters=filters) \
- .AndReturn([stacks[2:], True, True])
- api.heat.stacks_list(IsA(http.HttpRequest),
- marker=stacks[2].id,
- paginate=True,
- sort_dir='asc',
- filters=filters) \
- .AndReturn([stacks[:2], True, True])
- self.mox.ReplayAll()
-
- url = reverse('horizon:project:stacks:index')
- res = self.client.get(url)
- # get all
- self.assertEqual(len(res.context['stacks_table'].data),
- len(stacks))
- self.assertTemplateUsed(res, INDEX_TEMPLATE)
-
- res = self.client.get(url)
- # get first page with 2 items
- self.assertEqual(len(res.context['stacks_table'].data),
- settings.API_RESULT_PAGE_SIZE)
-
- url = "%s?%s=%s" % (reverse('horizon:project:stacks:index'),
- tables.StacksTable._meta.pagination_param,
- stacks[2].id)
- res = self.client.get(url)
- # get second page (item 3)
- self.assertEqual(len(res.context['stacks_table'].data), 1)
-
- url = "%s?%s=%s" % (reverse('horizon:project:stacks:index'),
- tables.StacksTable._meta.prev_pagination_param,
- stacks[2].id)
- res = self.client.get(url)
- # prev back to get first page with 2 pages
- self.assertEqual(len(res.context['stacks_table'].data),
- settings.API_RESULT_PAGE_SIZE)
-
- @test.create_stubs({api.heat: ('stack_create', 'template_validate'),
- api.neutron: ('network_list_for_tenant', )})
- def test_launch_stack(self):
- template = self.stack_templates.first()
- stack = self.stacks.first()
-
- api.heat.template_validate(IsA(http.HttpRequest),
- files={},
- template=hc_format.parse(template.data)) \
- .AndReturn(json.loads(template.validate))
-
- api.heat.stack_create(IsA(http.HttpRequest),
- stack_name=stack.stack_name,
- timeout_mins=60,
- disable_rollback=True,
- template=None,
- parameters=IsA(dict),
- password='password',
- files=None)
- api.neutron.network_list_for_tenant(IsA(http.HttpRequest),
- self.tenant.id) \
- .AndReturn(self.networks.list())
- api.neutron.network_list_for_tenant(IsA(http.HttpRequest),
- self.tenant.id) \
- .AndReturn(self.networks.list())
-
- self.mox.ReplayAll()
-
- url = reverse('horizon:project:stacks:select_template')
- res = self.client.get(url)
- self.assertTemplateUsed(res, 'project/stacks/select_template.html')
-
- form_data = {'template_source': 'raw',
- 'template_data': template.data,
- 'method': forms.TemplateForm.__name__}
- res = self.client.post(url, form_data)
- self.assertTemplateUsed(res, 'project/stacks/create.html')
-
- url = reverse('horizon:project:stacks:launch')
- form_data = {'template_source': 'raw',
- 'template_data': template.data,
- 'password': 'password',
- 'parameters': template.validate,
- 'stack_name': stack.stack_name,
- "timeout_mins": 60,
- "disable_rollback": True,
- "__param_DBUsername": "admin",
- "__param_LinuxDistribution": "F17",
- "__param_InstanceType": "m1.small",
- "__param_KeyName": "test",
- "__param_DBPassword": "admin",
- "__param_DBRootPassword": "admin",
- "__param_DBName": "wordpress",
- "__param_Network": self.networks.list()[0]['id'],
- 'method': forms.CreateStackForm.__name__}
- res = self.client.post(url, form_data)
- self.assertRedirectsNoFollow(res, INDEX_URL)
-
- @test.create_stubs({api.heat: ('stack_create', 'template_validate'),
- api.neutron: ('network_list_for_tenant', )})
- def test_launch_stack_with_environment(self):
- template = self.stack_templates.first()
- environment = self.stack_environments.first()
- stack = self.stacks.first()
-
- api.heat.template_validate(IsA(http.HttpRequest),
- files={},
- template=hc_format.parse(template.data),
- environment=environment.data) \
- .AndReturn(json.loads(template.validate))
-
- api.heat.stack_create(IsA(http.HttpRequest),
- stack_name=stack.stack_name,
- timeout_mins=60,
- disable_rollback=True,
- template=None,
- environment=environment.data,
- parameters=IsA(dict),
- password='password',
- files=None)
- api.neutron.network_list_for_tenant(IsA(http.HttpRequest),
- self.tenant.id) \
- .AndReturn(self.networks.list())
- api.neutron.network_list_for_tenant(IsA(http.HttpRequest),
- self.tenant.id) \
- .AndReturn(self.networks.list())
-
- self.mox.ReplayAll()
-
- url = reverse('horizon:project:stacks:select_template')
- res = self.client.get(url)
- self.assertTemplateUsed(res, 'project/stacks/select_template.html')
-
- form_data = {'template_source': 'raw',
- 'template_data': template.data,
- 'environment_source': 'raw',
- 'environment_data': environment.data,
- 'method': forms.TemplateForm.__name__}
- res = self.client.post(url, form_data)
- self.assertTemplateUsed(res, 'project/stacks/create.html')
-
- url = reverse('horizon:project:stacks:launch')
- form_data = {'template_source': 'raw',
- 'template_data': template.data,
- 'environment_source': 'raw',
- 'environment_data': environment.data,
- 'password': 'password',
- 'parameters': template.validate,
- 'stack_name': stack.stack_name,
- "timeout_mins": 60,
- "disable_rollback": True,
- "__param_DBUsername": "admin",
- "__param_LinuxDistribution": "F17",
- "__param_InstanceType": "m1.small",
- "__param_KeyName": "test",
- "__param_DBPassword": "admin",
- "__param_DBRootPassword": "admin",
- "__param_DBName": "wordpress",
- "__param_Network": self.networks.list()[0]['id'],
- 'method': forms.CreateStackForm.__name__}
- res = self.client.post(url, form_data)
- self.assertRedirectsNoFollow(res, INDEX_URL)
-
- @test.create_stubs({api.heat: ('template_validate',)})
- def test_launch_stack_with_hidden_parameters(self):
- template = {
- 'data': ('heat_template_version: 2013-05-23\n'
- 'parameters:\n'
- ' public_string:\n'
- ' type: string\n'
- ' secret_string:\n'
- ' type: string\n'
- ' hidden: true\n'),
- 'validate': {
- 'Description': 'No description',
- 'Parameters': {
- 'public_string': {
- 'Label': 'public_string',
- 'Description': '',
- 'Type': 'String',
- 'NoEcho': 'false'
- },
- 'secret_string': {
- 'Label': 'secret_string',
- 'Description': '',
- 'Type': 'String',
- 'NoEcho': 'true'
- }
- }
- }
- }
- api.heat.template_validate(IsA(http.HttpRequest),
- files={},
- template=hc_format.parse(template['data'])) \
- .AndReturn(template['validate'])
-
- self.mox.ReplayAll()
-
- url = reverse('horizon:project:stacks:select_template')
- res = self.client.get(url)
- self.assertTemplateUsed(res, 'project/stacks/select_template.html')
-
- form_data = {'template_source': 'raw',
- 'template_data': template['data'],
- 'method': forms.TemplateForm.__name__}
- res = self.client.post(url, form_data)
- self.assertTemplateUsed(res, 'project/stacks/create.html')
-
- # ensure the fields were rendered correctly
- if django.VERSION >= (1, 10):
- pattern = (' ')
- secret = (' ')
- else:
- pattern = (' ')
- secret = (' ')
-
- self.assertContains(res, pattern, html=True)
- self.assertContains(res, secret, html=True)
-
- @test.create_stubs({api.heat: ('template_validate',)})
- def test_launch_stack_with_parameter_group(self):
- template = {
- 'data': ('heat_template_version: 2013-05-23\n'
- 'parameters:\n'
- ' last_param:\n'
- ' type: string\n'
- ' first_param:\n'
- ' type: string\n'
- ' middle_param:\n'
- ' type: string\n'
- 'parameter_groups:\n'
- '- parameters:\n'
- ' - first_param\n'
- ' - middle_param\n'
- ' - last_param\n'),
- 'validate': {
- 'Description': 'No description',
- 'Parameters': {
- 'last_param': {
- 'Label': 'last_param',
- 'Description': '',
- 'Type': 'String',
- 'NoEcho': 'false'
- },
- 'first_param': {
- 'Label': 'first_param',
- 'Description': '',
- 'Type': 'String',
- 'NoEcho': 'false'
- },
- 'middle_param': {
- 'Label': 'middle_param',
- 'Description': '',
- 'Type': 'String',
- 'NoEcho': 'true'
- }
- },
- 'ParameterGroups': [
- {
- 'parameters': [
- 'first_param',
- 'middle_param',
- 'last_param'
- ]
- }
- ]
- }
- }
- api.heat.template_validate(IsA(http.HttpRequest),
- files={},
- template=hc_format.parse(template['data'])) \
- .AndReturn(template['validate'])
-
- self.mox.ReplayAll()
-
- url = reverse('horizon:project:stacks:select_template')
- res = self.client.get(url)
- self.assertTemplateUsed(res, 'project/stacks/select_template.html')
-
- form_data = {'template_source': 'raw',
- 'template_data': template['data'],
- 'method': forms.TemplateForm.__name__}
- res = self.client.post(url, form_data)
- self.assertTemplateUsed(res, 'project/stacks/create.html')
-
- # ensure the fields were rendered in the correct order
- regex = re.compile('^.*>first_param<.*>middle_param<.*>last_param<.*$',
- flags=re.DOTALL)
- self.assertRegexpMatches(res.content.decode('utf-8'), regex)
-
- @test.create_stubs({api.heat: ('stack_create', 'template_validate')})
- def test_launch_stack_parameter_types(self):
- template = {
- 'data': ('heat_template_version: 2013-05-23\n'
- 'parameters:\n'
- ' param1:\n'
- ' type: string\n'
- ' param2:\n'
- ' type: number\n'
- ' param3:\n'
- ' type: json\n'
- ' param4:\n'
- ' type: comma_delimited_list\n'
- ' param5:\n'
- ' type: boolean\n'),
- 'validate': {
- "Description": "No description",
- "Parameters": {
- "param1": {
- "Type": "String",
- "NoEcho": "false",
- "Description": "",
- "Label": "param1"
- },
- "param2": {
- "Type": "Number",
- "NoEcho": "false",
- "Description": "",
- "Label": "param2"
- },
- "param3": {
- "Type": "Json",
- "NoEcho": "false",
- "Description": "",
- "Label": "param3"
- },
- "param4": {
- "Type": "CommaDelimitedList",
- "NoEcho": "false",
- "Description": "",
- "Label": "param4"
- },
- "param5": {
- "Type": "Boolean",
- "NoEcho": "false",
- "Description": "",
- "Label": "param5"
- }
- }
- }
- }
- stack = self.stacks.first()
-
- api.heat.template_validate(IsA(http.HttpRequest),
- files={},
- template=hc_format.parse(template['data'])) \
- .AndReturn(template['validate'])
-
- api.heat.stack_create(IsA(http.HttpRequest),
- stack_name=stack.stack_name,
- timeout_mins=60,
- disable_rollback=True,
- template=hc_format.parse(template['data']),
- parameters={'param1': 'some string',
- 'param2': 42,
- 'param3': '{"key": "value"}',
- 'param4': 'a,b,c',
- 'param5': True},
- password='password',
- files={})
-
- self.mox.ReplayAll()
-
- url = reverse('horizon:project:stacks:select_template')
- res = self.client.get(url)
- self.assertTemplateUsed(res, 'project/stacks/select_template.html')
-
- form_data = {'template_source': 'raw',
- 'template_data': template['data'],
- 'method': forms.TemplateForm.__name__}
- res = self.client.post(url, form_data)
- self.assertTemplateUsed(res, 'project/stacks/create.html')
-
- # ensure the fields were rendered correctly
- if django.VERSION >= (1, 10):
- input_str = (' ')
- else:
- input_str = (' ')
-
- self.assertContains(res, input_str.format(1, 'text'), html=True)
- # the custom number spinner produces an input element
- # that doesn't match the input_strs above
- # validate with id alone
- self.assertContains(res, 'id="id___param_param2"')
- self.assertContains(res, input_str.format(3, 'text'), html=True)
- self.assertContains(res, input_str.format(4, 'text'), html=True)
- self.assertContains(
- res,
- ' ',
- html=True)
-
- # post some sample data and make sure it validates
- url = reverse('horizon:project:stacks:launch')
- form_data = {'template_source': 'raw',
- 'template_data': template['data'],
- 'password': 'password',
- 'parameters': json.dumps(template['validate']),
- 'stack_name': stack.stack_name,
- "timeout_mins": 60,
- "disable_rollback": True,
- "__param_param1": "some string",
- "__param_param2": 42,
- "__param_param3": '{"key": "value"}',
- "__param_param4": "a,b,c",
- "__param_param5": True,
- 'method': forms.CreateStackForm.__name__}
- res = self.client.post(url, form_data)
- self.assertRedirectsNoFollow(res, INDEX_URL)
-
- @test.create_stubs({api.heat: ('stack_update', 'stack_get', 'template_get',
- 'template_validate'),
- api.neutron: ('network_list_for_tenant', )})
- def test_edit_stack_template(self):
- template = self.stack_templates.first()
- stack = self.stacks.first()
-
- # GET to template form
- api.heat.stack_get(IsA(http.HttpRequest),
- stack.id).AndReturn(stack)
- # POST template form, validation
- api.heat.template_validate(IsA(http.HttpRequest),
- files={},
- template=hc_format.parse(template.data)) \
- .AndReturn(json.loads(template.validate))
-
- # GET to edit form
- api.heat.stack_get(IsA(http.HttpRequest),
- stack.id).AndReturn(stack)
- api.heat.template_get(IsA(http.HttpRequest),
- stack.id) \
- .AndReturn(json.loads(template.validate))
-
- # POST to edit form
- api.heat.stack_get(IsA(http.HttpRequest),
- stack.id).AndReturn(stack)
-
- fields = {
- 'stack_name': stack.stack_name,
- 'disable_rollback': True,
- 'timeout_mins': 61,
- 'password': 'password',
- 'template': None,
- 'parameters': IsA(dict),
- 'files': None
- }
- api.heat.stack_update(IsA(http.HttpRequest),
- stack_id=stack.id,
- **fields)
- api.neutron.network_list_for_tenant(IsA(http.HttpRequest),
- self.tenant.id) \
- .AndReturn(self.networks.list())
-
- self.mox.ReplayAll()
-
- url = reverse('horizon:project:stacks:change_template',
- args=[stack.id])
- res = self.client.get(url)
- self.assertTemplateUsed(res, 'project/stacks/change_template.html')
-
- form_data = {'template_source': 'raw',
- 'template_data': template.data,
- 'method': forms.ChangeTemplateForm.__name__}
- res = self.client.post(url, form_data)
-
- url = reverse('horizon:project:stacks:edit_stack',
- args=[stack.id, ])
- form_data = {'template_source': 'raw',
- 'template_data': template.data,
- 'password': 'password',
- 'parameters': template.validate,
- 'stack_name': stack.stack_name,
- 'stack_id': stack.id,
- "timeout_mins": 61,
- "disable_rollback": True,
- "__param_DBUsername": "admin",
- "__param_LinuxDistribution": "F17",
- "__param_InstanceType": "m1.small",
- "__param_KeyName": "test",
- "__param_DBPassword": "admin",
- "__param_DBRootPassword": "admin",
- "__param_DBName": "wordpress",
- "__param_Network": self.networks.list()[0]['id'],
- 'method': forms.EditStackForm.__name__}
- res = self.client.post(url, form_data)
- self.assertRedirectsNoFollow(res, INDEX_URL)
-
- def test_launch_stack_form_invalid_name_digit(self):
- self._test_launch_stack_invalid_name('2_StartWithDigit')
-
- def test_launch_stack_form_invalid_name_underscore(self):
- self._test_launch_stack_invalid_name('_StartWithUnderscore')
-
- def test_launch_stack_form_invalid_name_point(self):
- self._test_launch_stack_invalid_name('.StartWithPoint')
-
- @test.create_stubs({api.neutron: ('network_list_for_tenant', )})
- def _test_launch_stack_invalid_name(self, name):
- api.neutron.network_list_for_tenant(IsA(http.HttpRequest),
- self.tenant.id) \
- .AndReturn(self.networks.list())
- self.mox.ReplayAll()
-
- template = self.stack_templates.first()
- url = reverse('horizon:project:stacks:launch')
- form_data = {'template_source': 'raw',
- 'template_data': template.data,
- 'password': 'password',
- 'parameters': template.validate,
- 'stack_name': name,
- "timeout_mins": 60,
- "disable_rollback": True,
- "__param_DBUsername": "admin",
- "__param_LinuxDistribution": "F17",
- "__param_InstanceType": "m1.small",
- "__param_KeyName": "test",
- "__param_DBPassword": "admin",
- "__param_DBRootPassword": "admin",
- "__param_DBName": "wordpress",
- "__param_Network": self.networks.list()[0]['id'],
- 'method': forms.CreateStackForm.__name__}
-
- res = self.client.post(url, form_data)
- error = ('Name must start with a letter and may only contain letters, '
- 'numbers, underscores, periods and hyphens.')
-
- self.assertFormErrors(res, 1)
- self.assertFormError(res, "form", 'stack_name', error)
-
- def _test_stack_action(self, action):
- stack = self.stacks.first()
- filters = {}
- api.heat.stacks_list(IsA(http.HttpRequest),
- marker=None,
- paginate=True,
- sort_dir='desc',
- filters=filters) \
- .AndReturn([self.stacks.list(), True, True])
-
- getattr(api.heat, 'action_%s' % action)(IsA(http.HttpRequest),
- stack.id).AndReturn(stack)
-
- self.mox.ReplayAll()
-
- form_data = {"action": "stacks__%s__%s" % (action, stack.id)}
- res = self.client.post(INDEX_URL, form_data)
-
- self.assertNoFormErrors(res)
- self.assertRedirectsNoFollow(res, INDEX_URL)
-
- @test.create_stubs({api.heat: ('stacks_list', 'action_check',)})
- def test_check_stack(self):
- self._test_stack_action('check')
-
- @test.create_stubs({api.heat: ('stacks_list', 'action_suspend',)})
- def test_suspend_stack(self):
- self._test_stack_action('suspend')
-
- @test.create_stubs({api.heat: ('stacks_list', 'action_resume',)})
- def test_resume_stack(self):
- self._test_stack_action('resume')
-
- @test.create_stubs({api.heat: ('stack_preview', 'template_validate')})
- def test_preview_stack(self):
- template = self.stack_templates.first()
- stack = self.stacks.first()
-
- api.heat.template_validate(IsA(http.HttpRequest),
- files={},
- template=hc_format.parse(template.data)) \
- .AndReturn(json.loads(template.validate))
-
- api.heat.stack_preview(IsA(http.HttpRequest),
- stack_name=stack.stack_name,
- timeout_mins=60,
- disable_rollback=True,
- template=None,
- parameters=IsA(dict),
- files=None).AndReturn(stack)
-
- self.mox.ReplayAll()
-
- url = reverse('horizon:project:stacks:preview_template')
- res = self.client.get(url)
- self.assertTemplateUsed(res, 'project/stacks/preview_template.html')
-
- form_data = {'template_source': 'raw',
- 'template_data': template.data,
- 'method': forms.PreviewTemplateForm.__name__}
- res = self.client.post(url, form_data)
- self.assertTemplateUsed(res, 'project/stacks/preview.html')
-
- url = reverse('horizon:project:stacks:preview')
- form_data = {'template_source': 'raw',
- 'template_data': template.data,
- 'parameters': template.validate,
- 'stack_name': stack.stack_name,
- "timeout_mins": 60,
- "disable_rollback": True,
- "__param_DBUsername": "admin",
- "__param_LinuxDistribution": "F17",
- "__param_InstanceType": "m1.small",
- "__param_KeyName": "test",
- "__param_DBPassword": "admin",
- "__param_DBRootPassword": "admin",
- "__param_DBName": "wordpress",
- 'method': forms.PreviewStackForm.__name__}
- res = self.client.post(url, form_data)
- self.assertTemplateUsed(res, 'project/stacks/preview_details.html')
- self.assertEqual(res.context['stack_preview']['stack_name'],
- stack.stack_name)
-
- @test.create_stubs({api.heat: ('stack_get', 'template_get',
- 'resources_list')})
- def test_detail_stack_topology(self):
- stack = self.stacks.first()
- template = self.stack_templates.first()
- api.heat.stack_get(IsA(http.HttpRequest), stack.id) \
- .MultipleTimes().AndReturn(stack)
- api.heat.template_get(IsA(http.HttpRequest), stack.id) \
- .AndReturn(json.loads(template.validate))
- api.heat.resources_list(IsA(http.HttpRequest), stack.stack_name) \
- .AndReturn([])
- self.mox.ReplayAll()
-
- url = '?'.join([reverse(DETAIL_URL, args=[stack.id]),
- '='.join(['tab', 'stack_details__stack_topology'])])
- res = self.client.get(url)
- tab = res.context['tab_group'].get_tab('topology')
- d3_data = tab.data['d3_data']
- self.assertEqual(tab.template_name,
- 'project/stacks/_detail_topology.html')
- # status is CREATE_COMPLETE, so we expect the topology to display it
- self.assertIn('info_box', d3_data)
- self.assertIn('stack-green.svg', d3_data)
- self.assertIn('Create Complete', d3_data)
-
- @test.create_stubs({api.heat: ('stack_get', 'template_get'),
- project_api: ('d3_data',)})
- def test_detail_stack_overview(self):
- stack = self.stacks.first()
- template = self.stack_templates.first()
- api.heat.stack_get(IsA(http.HttpRequest), stack.id) \
- .MultipleTimes().AndReturn(stack)
- api.heat.template_get(IsA(http.HttpRequest), stack.id) \
- .AndReturn(json.loads(template.validate))
- project_api.d3_data(IsA(http.HttpRequest), stack_id=stack.id) \
- .AndReturn(json.dumps({"nodes": [], "stack": {}}))
- self.mox.ReplayAll()
-
- url = '?'.join([reverse(DETAIL_URL, args=[stack.id]),
- '='.join(['tab', 'stack_details__stack_overview'])])
- res = self.client.get(url)
- tab = res.context['tab_group'].get_tab('overview')
- overview_data = tab.data['stack']
- self.assertEqual(tab.template_name,
- 'project/stacks/_detail_overview.html')
- self.assertEqual(stack.stack_name, overview_data.stack_name)
-
- @test.create_stubs({api.heat: ('stack_get', 'template_get'),
- project_api: ('d3_data',)})
- def test_detail_stack_resources(self):
- stack = self.stacks.first()
- template = self.stack_templates.first()
- api.heat.stack_get(IsA(http.HttpRequest), stack.id) \
- .MultipleTimes().AndReturn(stack)
- api.heat.template_get(IsA(http.HttpRequest), stack.id) \
- .AndReturn(json.loads(template.validate))
- project_api.d3_data(IsA(http.HttpRequest), stack_id=stack.id) \
- .AndReturn(json.dumps({"nodes": [], "stack": {}}))
- self.mox.ReplayAll()
-
- url = '?'.join([reverse(DETAIL_URL, args=[stack.id]),
- '='.join(['tab', 'stack_details__resource_overview'])])
- res = self.client.get(url)
- tab = res.context['tab_group'].get_tab('resources')
- self.assertEqual(tab.template_name,
- 'project/stacks/_detail_resources.html')
-
- @test.create_stubs({api.heat: ('stack_get', 'template_get')})
- def test_detail_stack_template(self):
- stack = self.stacks.first()
- template = self.stack_templates.first()
- api.heat.stack_get(IsA(http.HttpRequest), stack.id) \
- .AndReturn(stack)
- api.heat.template_get(IsA(http.HttpRequest), stack.id) \
- .AndReturn(json.loads(template.validate))
- self.mox.ReplayAll()
-
- url = '?'.join([reverse(DETAIL_URL, args=[stack.id]),
- '='.join(['tab', 'stack_details__stack_template'])])
- res = self.client.get(url)
- tab = res.context['tab_group'].get_tab('stack_template')
- template_data = tab.data['stack_template']
- self.assertEqual(tab.template_name,
- 'project/stacks/_stack_template.html')
- self.assertIn(json.loads(template.validate)['Description'],
- template_data)
-
- @test.create_stubs({api.heat: ('resource_get', 'resource_metadata_get')})
- def test_resource_view(self):
- stack = self.stacks.first()
- resource = self.heat_resources.first()
- metadata = {}
- api.heat.resource_get(
- IsA(http.HttpRequest), stack.id, resource.resource_name) \
- .AndReturn(resource)
- api.heat.resource_metadata_get(
- IsA(http.HttpRequest), stack.id, resource.resource_name) \
- .AndReturn(metadata)
- self.mox.ReplayAll()
-
- url = reverse('horizon:project:stacks:resource',
- args=[stack.id, resource.resource_name])
- res = self.client.get(url)
- self.assertTemplateUsed(res, 'horizon/common/_detail.html')
- self.assertTemplateUsed(res, 'project/stacks/_resource_overview.html')
- self.assertEqual(res.context['resource'].logical_resource_id,
- resource.logical_resource_id)
-
-
-class TemplateFormTests(test.TestCase):
-
- class SimpleFile(object):
- def __init__(self, name, data):
- self.name = name
- self.data = data
-
- def read(self):
- return self.data
-
- def test_create_upload_form_attributes(self):
- attrs = forms.create_upload_form_attributes(
- 'env', 'url', 'Environment')
- self.assertEqual(attrs['data-envsource-url'], 'Environment')
-
- def test_clean_file_upload_form_url(self):
- kwargs = {'next_view': 'Launch Stack'}
- t = forms.TemplateForm({}, **kwargs)
- precleaned = {
- 'template_url': 'http://templateurl.com',
- }
- t.clean_uploaded_files('template', 'template', precleaned, {})
-
- self.assertEqual(precleaned['template_url'], 'http://templateurl.com')
-
- def test_clean_file_upload_form_multiple(self):
- kwargs = {'next_view': 'Launch Stack'}
- t = forms.TemplateForm({}, **kwargs)
- precleaned = {
- 'template_url': 'http://templateurl.com',
- 'template_data': 'http://templateurl.com',
- }
- self.assertRaises(
- exceptions.ValidationError,
- t.clean_uploaded_files,
- 'template',
- 'template',
- precleaned,
- {})
-
- def test_clean_file_upload_form_invalid_json(self):
- kwargs = {'next_view': 'Launch Stack'}
- t = forms.TemplateForm({}, **kwargs)
- precleaned = {
- 'template_data': 'http://templateurl.com',
- }
- json_str = '{notvalidjson::::::json/////json'
- files = {'template_upload':
- self.SimpleFile('template_name', json_str)}
-
- self.assertRaises(
- exceptions.ValidationError,
- t.clean_uploaded_files,
- 'template',
- 'template',
- precleaned,
- files)
-
- def test_clean_file_upload_form_valid_data(self):
- kwargs = {'next_view': 'Launch Stack'}
- t = forms.TemplateForm({}, **kwargs)
- precleaned = {
- 'template_data': 'http://templateurl.com',
- }
-
- json_str = '{"isvalid":"json"}'
- files = {'template_upload':
- self.SimpleFile('template_name', json_str)}
-
- t.clean_uploaded_files('template', 'template', precleaned, files)
- self.assertEqual(
- json_str,
- precleaned['template_data'])
diff --git a/openstack_dashboard/dashboards/project/stacks/urls.py b/openstack_dashboard/dashboards/project/stacks/urls.py
deleted file mode 100644
index c63a18fe62..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/urls.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from django.conf.urls import url
-
-from openstack_dashboard.dashboards.project.stacks import views
-
-urlpatterns = [
- url(r'^$', views.IndexView.as_view(), name='index'),
- url(r'^select_template$',
- views.SelectTemplateView.as_view(),
- name='select_template'),
- url(r'^launch$', views.CreateStackView.as_view(), name='launch'),
- url(r'^preview_template$',
- views.PreviewTemplateView.as_view(), name='preview_template'),
- url(r'^preview$', views.PreviewStackView.as_view(), name='preview'),
- url(r'^preview_details$',
- views.PreviewStackDetailsView.as_view(), name='preview_details'),
- url(r'^stack/(?P[^/]+)/$',
- views.DetailView.as_view(), name='detail'),
- url(r'^(?P[^/]+)/change_template$',
- views.ChangeTemplateView.as_view(), name='change_template'),
- url(r'^(?P[^/]+)/edit_stack$',
- views.EditStackView.as_view(), name='edit_stack'),
- url(r'^stack/(?P[^/]+)/(?P[^/]+)/$',
- views.ResourceView.as_view(), name='resource'),
- url(r'^get_d3_data/(?P[^/]+)/$',
- views.JSONView.as_view(), name='d3_data'),
-]
diff --git a/openstack_dashboard/dashboards/project/stacks/views.py b/openstack_dashboard/dashboards/project/stacks/views.py
deleted file mode 100644
index f5d47ec560..0000000000
--- a/openstack_dashboard/dashboards/project/stacks/views.py
+++ /dev/null
@@ -1,358 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import json
-from operator import attrgetter
-
-import yaml
-
-from django.core.urlresolvers import reverse
-from django.core.urlresolvers import reverse_lazy
-from django.http import HttpResponse
-from django.utils.translation import ugettext_lazy as _
-import django.views.generic
-
-from horizon import exceptions
-from horizon import forms
-from horizon import tables
-from horizon import tabs
-from horizon.utils import memoized
-from horizon import views
-from openstack_dashboard import api
-from openstack_dashboard.dashboards.project.stacks \
- import api as project_api
-from openstack_dashboard.dashboards.project.stacks \
- import forms as project_forms
-from openstack_dashboard.dashboards.project.stacks \
- import tables as project_tables
-from openstack_dashboard.dashboards.project.stacks \
- import tabs as project_tabs
-
-
-class IndexView(tables.DataTableView):
- table_class = project_tables.StacksTable
- page_title = _("Stacks")
-
- def __init__(self, *args, **kwargs):
- super(IndexView, self).__init__(*args, **kwargs)
- self._more = None
-
- def has_prev_data(self, table):
- return self._prev
-
- def has_more_data(self, table):
- return self._more
-
- def get_data(self):
- stacks = []
- filters = self.get_filters()
- prev_marker = self.request.GET.get(
- project_tables.StacksTable._meta.prev_pagination_param)
- if prev_marker is not None:
- sort_dir = 'asc'
- marker = prev_marker
- else:
- sort_dir = 'desc'
- marker = self.request.GET.get(
- project_tables.StacksTable._meta.pagination_param)
- try:
- stacks, self._more, self._prev = api.heat.stacks_list(
- self.request,
- marker=marker,
- paginate=True,
- sort_dir=sort_dir,
- filters=filters)
- if prev_marker is not None:
- stacks = sorted(stacks, key=attrgetter('creation_time'),
- reverse=True)
- except Exception:
- self._prev = False
- self._more = False
- msg = _('Unable to retrieve stack list.')
- exceptions.handle(self.request, msg)
- return stacks
-
-
-class SelectTemplateView(forms.ModalFormView):
- template_name = 'project/stacks/select_template.html'
- form_id = "select_template"
- form_class = project_forms.TemplateForm
- submit_label = _("Next")
- submit_url = reverse_lazy("horizon:project:stacks:select_template")
- success_url = reverse_lazy('horizon:project:stacks:launch')
- page_title = _("Select Template")
-
- def get_initial(self):
- initial = {}
- for name in [
- 'template_url',
- 'template_source',
- 'template_data',
- 'environment_source',
- 'environment_data'
- ]:
- tmp = self.request.GET.get(name)
- if tmp:
- initial[name] = tmp
- return initial
-
- def get_form_kwargs(self):
- kwargs = super(SelectTemplateView, self).get_form_kwargs()
- kwargs['next_view'] = CreateStackView
- return kwargs
-
-
-class ChangeTemplateView(forms.ModalFormView):
- template_name = 'project/stacks/change_template.html'
- form_id = "change_template"
- form_class = project_forms.ChangeTemplateForm
- submit_label = _("Next")
- submit_url = "horizon:project:stacks:change_template"
- cancel_url = reverse_lazy('horizon:project:stacks:index')
- success_url = reverse_lazy('horizon:project:stacks:edit_stack')
- page_title = _("Change Template")
-
- def get_context_data(self, **kwargs):
- context = super(ChangeTemplateView, self).get_context_data(**kwargs)
- args = (self.get_object().id,)
- context['submit_url'] = reverse(self.submit_url, args=args)
- return context
-
- @memoized.memoized_method
- def get_object(self):
- stack_id = self.kwargs['stack_id']
- try:
- self._stack = api.heat.stack_get(self.request, stack_id)
- except Exception:
- msg = _("Unable to retrieve stack.")
- redirect = reverse('horizon:project:stacks:index')
- exceptions.handle(self.request, msg, redirect=redirect)
- return self._stack
-
- def get_initial(self):
- stack = self.get_object()
- return {'stack_id': stack.id,
- 'stack_name': stack.stack_name
- }
-
- def get_form_kwargs(self):
- kwargs = super(ChangeTemplateView, self).get_form_kwargs()
- kwargs['next_view'] = EditStackView
- return kwargs
-
-
-class PreviewTemplateView(forms.ModalFormView):
- template_name = 'project/stacks/preview_template.html'
- form_id = "preview_template"
- form_class = project_forms.PreviewTemplateForm
- submit_label = _("Next")
- submit_url = reverse_lazy('horizon:project:stacks:preview_template')
- success_url = reverse_lazy('horizon:project:stacks:preview')
- page_title = _("Preview Template")
-
- def get_form_kwargs(self):
- kwargs = super(PreviewTemplateView, self).get_form_kwargs()
- kwargs['next_view'] = PreviewStackView
- return kwargs
-
-
-class CreateStackView(forms.ModalFormView):
- template_name = 'project/stacks/create.html'
- form_id = "launch_stack"
- form_class = project_forms.CreateStackForm
- submit_label = _("Launch")
- submit_url = reverse_lazy("horizon:project:stacks:launch")
- success_url = reverse_lazy('horizon:project:stacks:index')
- page_title = _("Launch Stack")
-
- def get_initial(self):
- initial = {}
- if 'environment_data' in self.kwargs:
- initial['environment_data'] = self.kwargs['environment_data']
- if 'parameters' in self.kwargs:
- initial['parameters'] = json.dumps(self.kwargs['parameters'])
- return initial
-
- def get_form_kwargs(self):
- kwargs = super(CreateStackView, self).get_form_kwargs()
- if 'parameters' in self.kwargs:
- kwargs['parameters'] = self.kwargs['parameters']
- else:
- data = json.loads(self.request.POST['parameters'])
- kwargs['parameters'] = data
- return kwargs
-
-
-# edit stack parameters, coming from template selector
-class EditStackView(CreateStackView):
- template_name = 'project/stacks/update.html'
- form_id = "update_stack"
- form_class = project_forms.EditStackForm
- submit_label = _("Update")
- submit_url = "horizon:project:stacks:edit_stack"
- success_url = reverse_lazy('horizon:project:stacks:index')
- page_title = _("Update Stack")
-
- def get_initial(self):
- initial = super(EditStackView, self).get_initial()
-
- initial['stack'] = self.get_object()['stack']
- if initial['stack']:
- initial['stack_id'] = initial['stack'].id
- initial['stack_name'] = initial['stack'].stack_name
-
- return initial
-
- def get_context_data(self, **kwargs):
- context = super(EditStackView, self).get_context_data(**kwargs)
- args = (self.get_object()['stack'].id,)
- context['submit_url'] = reverse(self.submit_url, args=args)
- return context
-
- @memoized.memoized_method
- def get_object(self):
- stack_id = self.kwargs['stack_id']
- try:
- stack = {}
- stack['stack'] = api.heat.stack_get(self.request, stack_id)
- stack['template'] = api.heat.template_get(self.request, stack_id)
- self._stack = stack
- except Exception:
- msg = _("Unable to retrieve stack.")
- redirect = reverse('horizon:project:stacks:index')
- exceptions.handle(self.request, msg, redirect=redirect)
- return self._stack
-
-
-class PreviewStackView(CreateStackView):
- template_name = 'project/stacks/preview.html'
- form_id = "preview_stack"
- form_class = project_forms.PreviewStackForm
- submit_label = _("Preview")
- submit_url = reverse_lazy('horizon:project:stacks:preview')
- success_url = reverse_lazy('horizon:project:stacks:index')
- page_title = _("Preview Stack")
-
- def get_form_kwargs(self):
- kwargs = super(CreateStackView, self).get_form_kwargs()
- kwargs['next_view'] = PreviewStackDetailsView
- return kwargs
-
-
-class PreviewStackDetailsView(forms.ModalFormMixin, views.HorizonTemplateView):
- template_name = 'project/stacks/preview_details.html'
- page_title = _("Preview Stack Details")
-
- def get_context_data(self, **kwargs):
- context = super(
- PreviewStackDetailsView, self).get_context_data(**kwargs)
- context['stack_preview'] = self.kwargs['stack_preview'].to_dict()
- return context
-
-
-class DetailView(tabs.TabView):
- tab_group_class = project_tabs.StackDetailTabs
- template_name = 'horizon/common/_detail.html'
- page_title = "{{ stack.stack_name|default:stack.id }}"
-
- def get_context_data(self, **kwargs):
- context = super(DetailView, self).get_context_data(**kwargs)
- stack = self.get_data(self.request, **kwargs)
- table = project_tables.StacksTable(self.request)
- context["stack"] = stack
- context["url"] = self.get_redirect_url()
- context["actions"] = table.render_row_actions(stack)
- return context
-
- @memoized.memoized_method
- def get_data(self, request, **kwargs):
- stack_id = kwargs['stack_id']
- try:
- stack = api.heat.stack_get(request, stack_id)
- request.session['stack_id'] = stack.id
- request.session['stack_name'] = stack.stack_name
- return stack
- except Exception:
- msg = _("Unable to retrieve stack.")
- exceptions.handle(request, msg, redirect=self.get_redirect_url())
-
- @memoized.memoized_method
- def get_template(self, request, **kwargs):
- try:
- stack_template = api.heat.template_get(
- request,
- kwargs['stack_id'])
- return yaml.safe_dump(stack_template, indent=2)
- except Exception:
- msg = _("Unable to retrieve stack template.")
- exceptions.handle(request, msg, redirect=self.get_redirect_url())
-
- def get_tabs(self, request, **kwargs):
- stack = self.get_data(request, **kwargs)
- stack_template = self.get_template(request, **kwargs)
- return self.tab_group_class(
- request, stack=stack, stack_template=stack_template, **kwargs)
-
- @staticmethod
- def get_redirect_url():
- return reverse('horizon:project:stacks:index')
-
-
-class ResourceView(tabs.TabView):
- tab_group_class = project_tabs.ResourceDetailTabs
- template_name = 'horizon/common/_detail.html'
- page_title = "{{ resource.resource_name|"\
- "default:resource.logical_resource_id }}"
-
- def get_context_data(self, **kwargs):
- context = super(ResourceView, self).get_context_data(**kwargs)
- context["resource"] = self.get_data(self.request, **kwargs)
- context["metadata"] = self.get_metadata(self.request, **kwargs)
- return context
-
- @memoized.memoized_method
- def get_data(self, request, **kwargs):
- try:
- resource = api.heat.resource_get(
- request,
- kwargs['stack_id'],
- kwargs['resource_name'])
- return resource
- except Exception:
- msg = _("Unable to retrieve resource.")
- redirect = reverse('horizon:project:stacks:index')
- exceptions.handle(request, msg, redirect=redirect)
-
- @memoized.memoized_method
- def get_metadata(self, request, **kwargs):
- try:
- metadata = api.heat.resource_metadata_get(
- request,
- kwargs['stack_id'],
- kwargs['resource_name'])
- return json.dumps(metadata, indent=2)
- except Exception:
- msg = _("Unable to retrieve metadata.")
- redirect = reverse('horizon:project:stacks:index')
- exceptions.handle(request, msg, redirect=redirect)
-
- def get_tabs(self, request, **kwargs):
- resource = self.get_data(request, **kwargs)
- metadata = self.get_metadata(request, **kwargs)
- return self.tab_group_class(
- request, resource=resource, metadata=metadata, **kwargs)
-
-
-class JSONView(django.views.generic.View):
- def get(self, request, stack_id=''):
- return HttpResponse(project_api.d3_data(request, stack_id=stack_id),
- content_type="application/json")
diff --git a/openstack_dashboard/enabled/_1610_orchestration_panel_group.py b/openstack_dashboard/enabled/_1610_orchestration_panel_group.py
deleted file mode 100644
index 986879ca81..0000000000
--- a/openstack_dashboard/enabled/_1610_orchestration_panel_group.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-
-# The slug of the panel group to be added to HORIZON_CONFIG. Required.
-PANEL_GROUP = 'orchestration'
-# The display name of the PANEL_GROUP. Required.
-PANEL_GROUP_NAME = _('Orchestration')
-# The slug of the dashboard the PANEL_GROUP associated with. Required.
-PANEL_GROUP_DASHBOARD = 'project'
diff --git a/openstack_dashboard/enabled/_1620_project_stacks_panel.py b/openstack_dashboard/enabled/_1620_project_stacks_panel.py
deleted file mode 100644
index b044fcca9d..0000000000
--- a/openstack_dashboard/enabled/_1620_project_stacks_panel.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# The slug of the panel to be added to HORIZON_CONFIG. Required.
-PANEL = 'stacks'
-# The slug of the dashboard the PANEL associated with. Required.
-PANEL_DASHBOARD = 'project'
-# The slug of the panel group the PANEL is associated with.
-PANEL_GROUP = 'orchestration'
-
-# Python panel class of the PANEL to be added.
-ADD_PANEL = 'openstack_dashboard.dashboards.project.stacks.panel.Stacks'
diff --git a/openstack_dashboard/enabled/_1630_project_resource_types_panel.py b/openstack_dashboard/enabled/_1630_project_resource_types_panel.py
deleted file mode 100644
index 8b048924f5..0000000000
--- a/openstack_dashboard/enabled/_1630_project_resource_types_panel.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# The slug of the panel to be added to HORIZON_CONFIG. Required.
-PANEL = 'stacks.resource_types'
-# The slug of the dashboard the PANEL associated with. Required.
-PANEL_DASHBOARD = 'project'
-# The slug of the panel group the PANEL is associated with.
-PANEL_GROUP = 'orchestration'
-
-# Python panel class of the PANEL to be added.
-ADD_PANEL = ('openstack_dashboard.dashboards.project.'
- 'stacks.resource_types.panel.ResourceTypes')
diff --git a/openstack_dashboard/enabled/_1640_project_template_versions_panel.py b/openstack_dashboard/enabled/_1640_project_template_versions_panel.py
deleted file mode 100644
index f31e040418..0000000000
--- a/openstack_dashboard/enabled/_1640_project_template_versions_panel.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# The slug of the panel to be added to HORIZON_CONFIG. Required.
-PANEL = 'stacks.template_versions'
-# The slug of the dashboard the PANEL associated with. Required.
-PANEL_DASHBOARD = 'project'
-# The slug of the panel group the PANEL is associated with.
-PANEL_GROUP = 'orchestration'
-
-# Python panel class of the PANEL to be added.
-ADD_PANEL = ('openstack_dashboard.dashboards.project.'
- 'stacks.template_versions.panel.TemplateVersions')
diff --git a/openstack_dashboard/exceptions.py b/openstack_dashboard/exceptions.py
index 520214d75c..e77e12b3e8 100644
--- a/openstack_dashboard/exceptions.py
+++ b/openstack_dashboard/exceptions.py
@@ -18,7 +18,6 @@
from cinderclient import exceptions as cinderclient
from glanceclient.common import exceptions as glanceclient
-from heatclient import exc as heatclient
from keystoneclient import exceptions as keystoneclient
from neutronclient.common import exceptions as neutronclient
from novaclient import exceptions as novaclient
@@ -32,7 +31,6 @@ UNAUTHORIZED = (
novaclient.Unauthorized,
glanceclient.Unauthorized,
neutronclient.Unauthorized,
- heatclient.HTTPUnauthorized,
)
@@ -42,7 +40,6 @@ NOT_FOUND = (
novaclient.NotFound,
glanceclient.NotFound,
neutronclient.NotFound,
- heatclient.HTTPNotFound,
)
@@ -62,7 +59,5 @@ RECOVERABLE = (
neutronclient.Forbidden,
neutronclient.NeutronClientException,
swiftclient.ClientException,
- heatclient.HTTPForbidden,
- heatclient.HTTPException,
requests.RequestException,
)
diff --git a/openstack_dashboard/local/local_settings.py.example b/openstack_dashboard/local/local_settings.py.example
index a4e34b9d54..36e698fea8 100644
--- a/openstack_dashboard/local/local_settings.py.example
+++ b/openstack_dashboard/local/local_settings.py.example
@@ -502,7 +502,6 @@ TIME_ZONE = "UTC"
# 'compute': 'nova_policy.json',
# 'volume': 'cinder_policy.json',
# 'image': 'glance_policy.json',
-# 'orchestration': 'heat_policy.json',
# 'network': 'neutron_policy.json',
#}
@@ -608,11 +607,6 @@ LOGGING = {
'level': 'DEBUG',
'propagate': False,
},
- 'heatclient': {
- 'handlers': ['console'],
- 'level': 'DEBUG',
- 'propagate': False,
- },
'swiftclient': {
'handlers': ['console'],
'level': 'DEBUG',
diff --git a/openstack_dashboard/settings.py b/openstack_dashboard/settings.py
index ba82951045..6027ea0aad 100644
--- a/openstack_dashboard/settings.py
+++ b/openstack_dashboard/settings.py
@@ -259,7 +259,6 @@ POLICY_FILES = {
'compute': 'nova_policy.json',
'volume': 'cinder_policy.json',
'image': 'glance_policy.json',
- 'orchestration': 'heat_policy.json',
'network': 'neutron_policy.json',
}
diff --git a/openstack_dashboard/static/app/core/openstack-service-api/heat.service.js b/openstack_dashboard/static/app/core/openstack-service-api/heat.service.js
deleted file mode 100644
index 78e60b046a..0000000000
--- a/openstack_dashboard/static/app/core/openstack-service-api/heat.service.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-(function () {
- 'use strict';
-
- angular
- .module('horizon.app.core.openstack-service-api')
- .factory('horizon.app.core.openstack-service-api.heat', heatAPI);
-
- heatAPI.$inject = [
- 'horizon.framework.util.http.service',
- 'horizon.framework.widgets.toast.service'
- ];
-
- /**
- * @ngdoc service
- * @name heatAPI
- * @param {Object} apiService
- * @param {Object} toastService
- * @description Provides direct pass through to Heat with NO abstraction.
- * @returns {Object} The service
- */
- function heatAPI(apiService, toastService) {
- var service = {
- validate: validate,
- getServices: getServices
- };
-
- return service;
-
- /**
- * @name validate
- * @description
- * Validate a template.
- *
- * @param {string} params
- * - template_url
- * Specifies the template to validate.
- *
- * @param {boolean} suppressError
- * If passed in, this will not show the default error handling
- * (horizon alert).
- * @returns {Object} The result of the API call
- */
- function validate(params, suppressError) {
- var promise = apiService.post('/api/heat/validate/', params);
- return suppressError ? promise : promise.error(function() {
- toastService.add('error', gettext('Unable to validate the template.'));
- });
- }
-
- /**
- * @name getServices
- * @description Get the list of heat services.
- *
- * @returns {Object} The listing result is an object with property "services." Each item is
- * a service.
- */
- function getServices() {
- return apiService.get('/api/heat/services/')
- .error(function () {
- toastService.add('error', gettext('Unable to retrieve the heat services.'));
- });
- }
- }
-
-}());
diff --git a/openstack_dashboard/static/app/core/openstack-service-api/heat.service.spec.js b/openstack_dashboard/static/app/core/openstack-service-api/heat.service.spec.js
deleted file mode 100644
index 0cdac559f5..0000000000
--- a/openstack_dashboard/static/app/core/openstack-service-api/heat.service.spec.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-(function() {
- 'use strict';
-
- describe('Heat API', function() {
- var testCall, service;
- var apiService = {};
- var toastService = {};
-
- beforeEach(
- module('horizon.mock.openstack-service-api',
- function($provide, initServices) {
- testCall = initServices($provide, apiService, toastService);
- })
- );
-
- beforeEach(module('horizon.app.core.openstack-service-api'));
-
- beforeEach(inject(['horizon.app.core.openstack-service-api.heat', function(heatAPI) {
- service = heatAPI;
- }]));
-
- it('defines the service', function() {
- expect(service).toBeDefined();
- });
-
- var tests = [
- {
- 'func': 'validate',
- 'method': 'post',
- 'path': '/api/heat/validate/',
- 'data': {
- 'template_url':'http://localhost/test.template'
- },
- 'error': 'Unable to validate the template.',
- 'testInput': [
- {
- 'template_url':'http://localhost/test.template'
- }
- ]
- },
- {
- 'func': 'getServices',
- 'method': 'get',
- 'path': '/api/heat/services/',
- 'error': 'Unable to retrieve the heat services.'
- }
- ];
-
- // Iterate through the defined tests and apply as Jasmine specs.
- angular.forEach(tests, function(params) {
- it('defines the ' + params.func + ' call properly', function() {
- var callParams = [apiService, service, toastService, params];
- testCall.apply(this, callParams);
- });
- });
-
- it('suppresses the error for template validation as instructed by the param', function() {
- spyOn(apiService, 'post').and.returnValue("promise");
- expect(service.validate("whatever", true)).toBe("promise");
- });
-
- });
-
-})();
diff --git a/openstack_dashboard/test/api_tests/heat_rest_tests.py b/openstack_dashboard/test/api_tests/heat_rest_tests.py
deleted file mode 100644
index ef5cc0f7c6..0000000000
--- a/openstack_dashboard/test/api_tests/heat_rest_tests.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-import json
-
-import mock
-
-from openstack_dashboard import api
-from openstack_dashboard.api.rest import heat
-from openstack_dashboard.test import helpers as test
-
-
-class ValidateRestTestCase(test.TestCase):
- @mock.patch.object(heat.api, 'heat')
- def test_validate_post(self, hc):
- body = '''{"template_url":"http://localhost/template.yaml"}'''
- request = self.mock_rest_request(body=body)
- hc.template_validate.return_value = ({'Description': 'foo'})
- response = heat.Validate().post(request)
- self.assertStatusCode(response, 200)
- self.assertEqual(response.json, {"Description": "foo"})
- kwargs = json.loads(body)
- hc.template_validate.assert_called_once_with(request, **kwargs)
-
-
-class HeatRestTestCase(test.TestCase):
- #
- # Services
- #
-
- @test.create_stubs({api.base: ('is_service_enabled',)})
- @mock.patch.object(heat.api, 'heat')
- def test_services_get(self, hc):
- request = self.mock_rest_request(GET={})
-
- api.base.is_service_enabled(request, 'orchestration').AndReturn(True)
-
- hc.service_list.return_value = [
- mock.Mock(**{'to_dict.return_value': {'id': '1'}}),
- mock.Mock(**{'to_dict.return_value': {'id': '2'}})
- ]
- self.mox.ReplayAll()
-
- response = heat.Services().get(request)
- self.assertStatusCode(response, 200)
- self.assertEqual(response.content.decode('utf-8'),
- '{"items": [{"id": "1"}, {"id": "2"}]}')
- hc.service_list.assert_called_once_with(request)
-
- @test.create_stubs({api.base: ('is_service_enabled',)})
- def test_services_get_disabled(self):
- request = self.mock_rest_request(GET={})
-
- api.base.is_service_enabled(request, 'orchestration').AndReturn(False)
-
- self.mox.ReplayAll()
-
- response = heat.Services().get(request)
- self.assertStatusCode(response, 501)
diff --git a/openstack_dashboard/test/api_tests/heat_tests.py b/openstack_dashboard/test/api_tests/heat_tests.py
deleted file mode 100644
index d241277771..0000000000
--- a/openstack_dashboard/test/api_tests/heat_tests.py
+++ /dev/null
@@ -1,358 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-import six
-
-from django.conf import settings
-from django.test.utils import override_settings
-
-from horizon import exceptions
-from openstack_dashboard import api
-from openstack_dashboard.test import helpers as test
-
-
-class HeatApiTests(test.APITestCase):
- def test_stack_list(self):
- api_stacks = self.stacks.list()
- limit = getattr(settings, 'API_RESULT_LIMIT', 1000)
-
- heatclient = self.stub_heatclient()
- heatclient.stacks = self.mox.CreateMockAnything()
- heatclient.stacks.list(limit=limit,
- sort_dir='desc',
- sort_key='created_at',) \
- .AndReturn(iter(api_stacks))
- self.mox.ReplayAll()
- stacks, has_more, has_prev = api.heat.stacks_list(self.request)
- self.assertItemsEqual(stacks, api_stacks)
- self.assertFalse(has_more)
- self.assertFalse(has_prev)
-
- @override_settings(API_RESULT_PAGE_SIZE=2)
- def test_stack_list_sort_options(self):
- # Verify that sort_dir and sort_key work
- api_stacks = self.stacks.list()
- limit = getattr(settings, 'API_RESULT_LIMIT', 1000)
- sort_dir = 'asc'
- sort_key = 'size'
-
- heatclient = self.stub_heatclient()
- heatclient.stacks = self.mox.CreateMockAnything()
- heatclient.stacks.list(limit=limit,
- sort_dir=sort_dir,
- sort_key=sort_key,) \
- .AndReturn(iter(api_stacks))
- self.mox.ReplayAll()
-
- stacks, has_more, has_prev = api.heat.stacks_list(self.request,
- sort_dir=sort_dir,
- sort_key=sort_key)
- self.assertItemsEqual(stacks, api_stacks)
- self.assertFalse(has_more)
- self.assertFalse(has_prev)
-
- @override_settings(API_RESULT_PAGE_SIZE=20)
- def test_stack_list_pagination_less_page_size(self):
- api_stacks = self.stacks.list()
- page_size = settings.API_RESULT_PAGE_SIZE
- sort_dir = 'desc'
- sort_key = 'created_at'
-
- heatclient = self.stub_heatclient()
- heatclient.stacks = self.mox.CreateMockAnything()
- heatclient.stacks.list(limit=page_size + 1,
- sort_dir=sort_dir,
- sort_key=sort_key,) \
- .AndReturn(iter(api_stacks))
- self.mox.ReplayAll()
-
- stacks, has_more, has_prev = api.heat.stacks_list(self.request,
- sort_dir=sort_dir,
- sort_key=sort_key,
- paginate=True)
- expected_stacks = api_stacks[:page_size]
- self.assertItemsEqual(stacks, expected_stacks)
- self.assertFalse(has_more)
- self.assertFalse(has_prev)
-
- @override_settings(API_RESULT_PAGE_SIZE=10)
- def test_stack_list_pagination_equal_page_size(self):
- api_stacks = self.stacks.list()
- page_size = settings.API_RESULT_PAGE_SIZE
- sort_dir = 'desc'
- sort_key = 'created_at'
-
- heatclient = self.stub_heatclient()
- heatclient.stacks = self.mox.CreateMockAnything()
- heatclient.stacks.list(limit=page_size + 1,
- sort_dir=sort_dir,
- sort_key=sort_key,) \
- .AndReturn(iter(api_stacks))
- self.mox.ReplayAll()
-
- stacks, has_more, has_prev = api.heat.stacks_list(self.request,
- sort_dir=sort_dir,
- sort_key=sort_key,
- paginate=True)
- expected_stacks = api_stacks[:page_size]
- self.assertItemsEqual(stacks, expected_stacks)
- self.assertFalse(has_more)
- self.assertFalse(has_prev)
-
- @override_settings(API_RESULT_PAGE_SIZE=2)
- def test_stack_list_pagination_marker(self):
- page_size = getattr(settings, 'API_RESULT_PAGE_SIZE', 20)
- sort_dir = 'desc'
- sort_key = 'created_at'
- marker = 'nonsense'
-
- api_stacks = self.stacks.list()
-
- heatclient = self.stub_heatclient()
- heatclient.stacks = self.mox.CreateMockAnything()
- heatclient.stacks.list(limit=page_size + 1,
- marker=marker,
- sort_dir=sort_dir,
- sort_key=sort_key,) \
- .AndReturn(iter(api_stacks[:page_size + 1]))
- self.mox.ReplayAll()
-
- stacks, has_more, has_prev = api.heat.stacks_list(self.request,
- marker=marker,
- paginate=True,
- sort_dir=sort_dir,
- sort_key=sort_key,)
-
- self.assertEqual(len(stacks), page_size)
- self.assertItemsEqual(stacks, api_stacks[:page_size])
- self.assertTrue(has_more)
- self.assertTrue(has_prev)
-
- @override_settings(API_RESULT_PAGE_SIZE=2)
- def test_stack_list_pagination_marker_prev(self):
- page_size = getattr(settings, 'API_RESULT_PAGE_SIZE', 20)
- sort_dir = 'asc'
- sort_key = 'created_at'
- marker = 'nonsense'
-
- api_stacks = self.stacks.list()
-
- heatclient = self.stub_heatclient()
- heatclient.stacks = self.mox.CreateMockAnything()
- heatclient.stacks.list(limit=page_size + 1,
- marker=marker,
- sort_dir=sort_dir,
- sort_key=sort_key,) \
- .AndReturn(iter(api_stacks[:page_size + 1]))
- self.mox.ReplayAll()
-
- stacks, has_more, has_prev = api.heat.stacks_list(self.request,
- marker=marker,
- paginate=True,
- sort_dir=sort_dir,
- sort_key=sort_key,)
-
- self.assertEqual(len(stacks), page_size)
- self.assertItemsEqual(stacks, api_stacks[:page_size])
- self.assertTrue(has_more)
- self.assertTrue(has_prev)
-
- def test_template_get(self):
- api_stacks = self.stacks.list()
- stack_id = api_stacks[0].id
- mock_data_template = self.stack_templates.list()[0]
-
- heatclient = self.stub_heatclient()
- heatclient.stacks = self.mox.CreateMockAnything()
- heatclient.stacks.template(stack_id).AndReturn(mock_data_template)
- self.mox.ReplayAll()
-
- template = api.heat.template_get(self.request, stack_id)
- self.assertEqual(mock_data_template.data, template.data)
-
- def test_stack_create(self):
- api_stacks = self.stacks.list()
- stack = api_stacks[0]
-
- heatclient = self.stub_heatclient()
- heatclient.stacks = self.mox.CreateMockAnything()
- form_data = {'timeout_mins': 600}
- password = 'secret'
- heatclient.stacks.create(**form_data).AndReturn(stack)
- self.mox.ReplayAll()
-
- returned_stack = api.heat.stack_create(self.request,
- password,
- **form_data)
- from heatclient.v1 import stacks
- self.assertIsInstance(returned_stack, stacks.Stack)
-
- def test_stack_update(self):
- api_stacks = self.stacks.list()
- stack = api_stacks[0]
- stack_id = stack.id
-
- heatclient = self.stub_heatclient()
- heatclient.stacks = self.mox.CreateMockAnything()
- form_data = {'timeout_mins': 600}
- password = 'secret'
- heatclient.stacks.update(stack_id, **form_data).AndReturn(stack)
- self.mox.ReplayAll()
-
- returned_stack = api.heat.stack_update(self.request,
- stack_id,
- password,
- **form_data)
- from heatclient.v1 import stacks
- self.assertIsInstance(returned_stack, stacks.Stack)
-
- def test_snapshot_create(self):
- stack_id = self.stacks.first().id
- snapshot_create = self.stack_snapshot_create.list()[0]
-
- heatclient = self.stub_heatclient()
- heatclient.stacks = self.mox.CreateMockAnything()
- heatclient.stacks.snapshot(stack_id).AndReturn(snapshot_create)
- self.mox.ReplayAll()
-
- returned_snapshot_create_info = api.heat.snapshot_create(self.request,
- stack_id)
-
- self.assertEqual(returned_snapshot_create_info, snapshot_create)
-
- def test_snapshot_list(self):
- stack_id = self.stacks.first().id
- snapshot_list = self.stack_snapshot.list()
-
- heatclient = self.stub_heatclient()
- heatclient.stacks = self.mox.CreateMockAnything()
- heatclient.stacks.snapshot_list(stack_id).AndReturn(snapshot_list)
- self.mox.ReplayAll()
-
- returned_snapshots = api.heat.snapshot_list(self.request, stack_id)
-
- self.assertItemsEqual(returned_snapshots, snapshot_list)
-
- def test_get_template_files_with_template_data(self):
- tmpl = '''
- # comment
-
- heat_template_version: 2013-05-23
- resources:
- server1:
- type: OS::Nova::Server
- properties:
- flavor: m1.medium
- image: cirros
- '''
- expected_files = {}
- files = api.heat.get_template_files(template_data=tmpl)[0]
- self.assertEqual(files, expected_files)
-
- def test_get_template_files(self):
- tmpl = '''
- # comment
-
- heat_template_version: 2013-05-23
- resources:
- server1:
- type: OS::Nova::Server
- properties:
- flavor: m1.medium
- image: cirros
- user_data_format: RAW
- user_data:
- get_file: http://test.example/example
- '''
- expected_files = {u'http://test.example/example': b'echo "test"'}
- url = 'http://test.example/example'
- data = b'echo "test"'
- self.mox.StubOutWithMock(six.moves.urllib.request, 'urlopen')
- six.moves.urllib.request.urlopen(url).AndReturn(
- six.BytesIO(data))
- self.mox.ReplayAll()
- files = api.heat.get_template_files(template_data=tmpl)[0]
- self.assertEqual(files, expected_files)
-
- def test_get_template_files_with_template_url(self):
- url = 'https://test.example/example.yaml'
- data = b'''
- # comment
-
- heat_template_version: 2013-05-23
- resources:
- server1:
- type: OS::Nova::Server
- properties:
- flavor: m1.medium
- image: cirros
- user_data_format: RAW
- user_data:
- get_file: http://test.example/example
- '''
- url2 = 'http://test.example/example'
- data2 = b'echo "test"'
- expected_files = {'http://test.example/example': b'echo "test"'}
- self.mox.StubOutWithMock(six.moves.urllib.request, 'urlopen')
- six.moves.urllib.request.urlopen(url).AndReturn(
- six.BytesIO(data))
- six.moves.urllib.request.urlopen(url2).AndReturn(
- six.BytesIO(data2))
- self.mox.ReplayAll()
- files = api.heat.get_template_files(template_url=url)[0]
- self.assertEqual(files, expected_files)
-
- def test_get_template_files_invalid(self):
- tmpl = '''
- # comment
-
- heat_template_version: 2013-05-23
- resources:
- server1:
- type: OS::Nova::Server
- properties:
- flavor: m1.medium
- image: cirros
- user_data_format: RAW
- user_data:
- get_file: file:///example
- '''
- try:
- api.heat.get_template_files(template_data=tmpl)[0]
- except exceptions.GetFileError:
- self.assertRaises(exceptions.GetFileError)
-
- def test_template_version_list(self):
- api_template_versions = self.template_versions.list()
-
- heatclient = self.stub_heatclient()
- heatclient.template_versions = self.mox.CreateMockAnything()
- heatclient.template_versions.list().AndReturn(api_template_versions)
- self.mox.ReplayAll()
-
- template_versions = api.heat.template_version_list(self.request)
-
- self.assertItemsEqual(template_versions, api_template_versions)
-
- def test_template_function_list(self):
- template_version = self.template_versions.first().version
- api_template_functions = self.template_functions.list()
-
- heatclient = self.stub_heatclient()
- heatclient.template_versions = self.mox.CreateMockAnything()
- heatclient.template_versions.get(
- template_version).AndReturn(api_template_functions)
- self.mox.ReplayAll()
-
- template_functions = api.heat.template_function_list(
- self.request, template_version)
-
- self.assertItemsEqual(template_functions, api_template_functions)
diff --git a/openstack_dashboard/test/helpers.py b/openstack_dashboard/test/helpers.py
index 1b8fe87614..8970c3a1be 100644
--- a/openstack_dashboard/test/helpers.py
+++ b/openstack_dashboard/test/helpers.py
@@ -37,7 +37,6 @@ from django.utils import http
from cinderclient import client as cinder_client
import glanceclient
-from heatclient import client as heat_client
from keystoneclient.v2_0 import client as keystone_client
import mock
from mox3 import mox
@@ -433,7 +432,6 @@ class APITestCase(TestCase):
self._original_novaclient = api.nova.novaclient
self._original_neutronclient = api.neutron.neutronclient
self._original_cinderclient = api.cinder.cinderclient
- self._original_heatclient = api.heat.heatclient
# Replace the clients with our stubs.
api.glance.glanceclient = fake_glanceclient
@@ -441,8 +439,6 @@ class APITestCase(TestCase):
api.nova.novaclient = fake_novaclient
api.neutron.neutronclient = lambda request: self.stub_neutronclient()
api.cinder.cinderclient = lambda request: self.stub_cinderclient()
- api.heat.heatclient = (lambda request, password=None:
- self.stub_heatclient())
def tearDown(self):
super(APITestCase, self).tearDown()
@@ -451,7 +447,6 @@ class APITestCase(TestCase):
api.keystone.keystoneclient = self._original_keystoneclient
api.neutron.neutronclient = self._original_neutronclient
api.cinder.cinderclient = self._original_cinderclient
- api.heat.heatclient = self._original_heatclient
def stub_novaclient(self):
if not hasattr(self, "novaclient"):
@@ -518,12 +513,6 @@ class APITestCase(TestCase):
expected_calls -= 1
return self.swiftclient
- def stub_heatclient(self):
- if not hasattr(self, "heatclient"):
- self.mox.StubOutWithMock(heat_client, 'Client')
- self.heatclient = self.mox.CreateMock(heat_client.Client)
- return self.heatclient
-
class APIMockTestCase(APITestCase):
def stub_cinderclient(self):
diff --git a/openstack_dashboard/test/integration_tests/config.py b/openstack_dashboard/test/integration_tests/config.py
index 668bc1d321..43cb7aab49 100644
--- a/openstack_dashboard/test/integration_tests/config.py
+++ b/openstack_dashboard/test/integration_tests/config.py
@@ -80,8 +80,6 @@ NetworkGroup = [
AvailableServiceGroup = [
cfg.BoolOpt('neutron',
default=True),
- cfg.BoolOpt('heat',
- default=True),
]
SeleniumGroup = [
diff --git a/openstack_dashboard/test/integration_tests/horizon.conf b/openstack_dashboard/test/integration_tests/horizon.conf
index a83249956a..9f5de9fcf1 100644
--- a/openstack_dashboard/test/integration_tests/horizon.conf
+++ b/openstack_dashboard/test/integration_tests/horizon.conf
@@ -77,8 +77,6 @@ tenant_network_cidr=10.100.0.0/16
[service_available]
# Whether is Neutron expected to be available (boolean value)
neutron=True
-# Whether is Heat expected to be available (boolean value)
-heat=True
[scenario]
# ssh username for image file (string value)
diff --git a/openstack_dashboard/test/integration_tests/pages/navigation.py b/openstack_dashboard/test/integration_tests/pages/navigation.py
index d348a4f7ad..9791782bda 100644
--- a/openstack_dashboard/test/integration_tests/pages/navigation.py
+++ b/openstack_dashboard/test/integration_tests/pages/navigation.py
@@ -106,13 +106,6 @@ class Navigation(object):
"Containers",
)
},
- "Orchestration":
- {
- ITEMS:
- (
- "Stacks",
- )
- }
},
"Admin":
{
diff --git a/openstack_dashboard/test/integration_tests/pages/project/orchestration/__init__.py b/openstack_dashboard/test/integration_tests/pages/project/orchestration/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/openstack_dashboard/test/integration_tests/pages/project/orchestration/stackspage.py b/openstack_dashboard/test/integration_tests/pages/project/orchestration/stackspage.py
deleted file mode 100644
index 3b83d03644..0000000000
--- a/openstack_dashboard/test/integration_tests/pages/project/orchestration/stackspage.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from openstack_dashboard.test.integration_tests import config
-from openstack_dashboard.test.integration_tests.pages import basepage
-from openstack_dashboard.test.integration_tests.regions import forms
-from openstack_dashboard.test.integration_tests.regions import tables
-
-
-class StacksTable(tables.TableRegion):
- name = "stacks"
- SELECT_TEMPLATE_FORM_FIELDS = ("template_source", "template_upload",
- "template_data", "template_url",
- "environment_source", "environment_upload",
- "environment_data")
- LAUNCH_STACK_FORM_FIELDS = ("stack_name", "timeout_mins",
- "enable_rollback", "password")
-
- @tables.bind_table_action('launch')
- def select_template(self, launch_button):
- launch_button.click()
- return forms.FormRegion(
- self.driver, self.conf,
- field_mappings=self.SELECT_TEMPLATE_FORM_FIELDS)
-
- def launch_stack(self):
- return forms.FormRegion(self.driver, self.conf,
- field_mappings=self.LAUNCH_STACK_FORM_FIELDS)
-
- @tables.bind_table_action('delete')
- def delete_stack(self, delete_button):
- delete_button.click()
- return forms.BaseFormRegion(self.driver, self.conf)
-
-
-class StacksPage(basepage.BaseNavigationPage):
- DEFAULT_TEMPLATE_SOURCE = 'raw'
-
- CONFIG = config.get_config()
- DEFAULT_PASSWORD = CONFIG.identity.admin_password
- STACKS_TABLE_NAME_COLUMN = 'name'
- STACKS_TABLE_STATUS_COLUMN = 'stack_status'
-
- def __init__(self, driver, conf):
- super(StacksPage, self).__init__(driver, conf)
- self._page_title = "Stacks"
-
- @property
- def stacks_table(self):
- return StacksTable(self.driver, self.conf)
-
- def _get_row_with_stack_name(self, name):
- return self.stacks_table.get_row(self.STACKS_TABLE_NAME_COLUMN, name)
-
- def create_stack(self, stack_name, template_data,
- template_source=DEFAULT_TEMPLATE_SOURCE,
- environment_source=None,
- environment_upload=None,
- timeout_mins=None,
- enable_rollback=None,
- password=DEFAULT_PASSWORD):
- select_template_form = self.stacks_table.select_template()
- select_template_form.template_source.value = template_source
- select_template_form.template_data.text = template_data
- select_template_form.submit()
- launch_stack_form = self.stacks_table.launch_stack()
- launch_stack_form.stack_name.text = stack_name
- launch_stack_form.password.text = password
- launch_stack_form.submit()
-
- def delete_stack(self, name):
- row = self._get_row_with_stack_name(name)
- row.mark()
- confirm_delete_stacks_form = self.stacks_table.delete_stack()
- confirm_delete_stacks_form.submit()
-
- def is_stack_present(self, name):
- return bool(self._get_row_with_stack_name(name))
-
- def is_stack_create_complete(self, name):
- def cell_getter():
- row = self._get_row_with_stack_name(name)
- return row and row.cells[self.STACKS_TABLE_STATUS_COLUMN]
-
- return bool(self.stacks_table.wait_cell_status(cell_getter,
- 'Create Complete'))
-
- def is_stack_deleted(self, name):
- return self.stacks_table.is_row_deleted(
- lambda: self._get_row_with_stack_name(name))
diff --git a/openstack_dashboard/test/integration_tests/tests/test_stacks.py b/openstack_dashboard/test/integration_tests/tests/test_stacks.py
deleted file mode 100644
index 7c9ff95ba0..0000000000
--- a/openstack_dashboard/test/integration_tests/tests/test_stacks.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-import os
-
-from openstack_dashboard.test.integration_tests import decorators
-from openstack_dashboard.test.integration_tests import helpers
-from openstack_dashboard.test.integration_tests.regions import messages
-
-
-class TestStacks(helpers.AdminTestCase):
- KEYPAIR_NAME = 'keypair_for_stack'
- STACKS_NAME = helpers.gen_random_resource_name('stack', timestamp=False)
- STACK_TEMPLATE_PATH = os.path.join(
- os.path.dirname(__file__), 'test-data/stack_template')
-
- def setUp(self):
- super(TestStacks, self).setUp()
- keypair_page = self.home_pg.\
- go_to_compute_accessandsecurity_keypairspage()
- keypair_page.create_keypair(self.KEYPAIR_NAME)
- keypair_page = self.home_pg.\
- go_to_compute_accessandsecurity_keypairspage()
- self.assertTrue(keypair_page.is_keypair_present(self.KEYPAIR_NAME))
-
- def cleanup():
- keypair_page = self.home_pg.\
- go_to_compute_accessandsecurity_keypairspage()
- keypair_page.delete_keypairs(self.KEYPAIR_NAME)
- keypair_page.find_message_and_dismiss(messages.SUCCESS)
-
- self.addCleanup(cleanup)
-
- @decorators.skip_because(bugs=['1584057'])
- @decorators.services_required("heat")
- def test_create_delete_stack(self):
- """tests the stack creation and deletion functionality
-
- * creates a new stack
- * verifies the stack appears in the stacks table in Create Complete
- state
- * deletes the newly created stack
- * verifies the stack does not appear in the table after deletion
- """
- with open(self.STACK_TEMPLATE_PATH, 'r') as f:
- template = f.read()
- input_template = template.format(self.KEYPAIR_NAME,
- self.CONFIG.image.images_list[0],
- "public")
- stacks_page = self.home_pg.go_to_orchestration_stackspage()
-
- stacks_page.create_stack(self.STACKS_NAME, input_template)
- self.assertTrue(
- stacks_page.find_message_and_dismiss(messages.INFO))
- self.assertFalse(
- stacks_page.find_message_and_dismiss(messages.ERROR))
- self.assertTrue(stacks_page.is_stack_present(self.STACKS_NAME))
- self.assertTrue(stacks_page.is_stack_create_complete(self.STACKS_NAME))
-
- stacks_page.delete_stack(self.STACKS_NAME)
- self.assertTrue(
- stacks_page.find_message_and_dismiss(messages.SUCCESS))
- self.assertFalse(
- stacks_page.find_message_and_dismiss(messages.ERROR))
- self.assertTrue(stacks_page.is_stack_deleted(self.STACKS_NAME))
diff --git a/openstack_dashboard/test/test_data/exceptions.py b/openstack_dashboard/test/test_data/exceptions.py
index 8f6e90bf10..9364d6379c 100644
--- a/openstack_dashboard/test/test_data/exceptions.py
+++ b/openstack_dashboard/test/test_data/exceptions.py
@@ -14,7 +14,6 @@
from cinderclient import exceptions as cinder_exceptions
import glanceclient.exc as glance_exceptions
-import heatclient.exc as heat_exceptions
from keystoneclient import exceptions as keystone_exceptions
from neutronclient.common import exceptions as neutron_exceptions
from novaclient import exceptions as nova_exceptions
@@ -81,6 +80,3 @@ def data(TEST):
cinder_exception = cinder_exceptions.BadRequest
TEST.exceptions.cinder = create_stubbed_exception(cinder_exception)
-
- heat_exception = heat_exceptions.HTTPException
- TEST.exceptions.heat = create_stubbed_exception(heat_exception)
diff --git a/openstack_dashboard/test/test_data/heat_data.py b/openstack_dashboard/test/test_data/heat_data.py
deleted file mode 100644
index 61ea1b91d1..0000000000
--- a/openstack_dashboard/test/test_data/heat_data.py
+++ /dev/null
@@ -1,617 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from heatclient.v1 import resource_types
-from heatclient.v1 import resources
-from heatclient.v1 import services
-from heatclient.v1 import stacks
-from heatclient.v1 import template_versions
-
-from openstack_dashboard.test.test_data import utils
-
-# A slightly hacked up copy of a sample cloudformation template for testing.
-TEMPLATE = """
-{
-"AWSTemplateFormatVersion": "2010-09-09",
-"Description": "AWS CloudFormation Sample Template.",
-"Parameters": {
-"KeyName": {
-"Description": "Name of an EC2 Key Pair to enable SSH access to the instances",
-"Type": "String"
-},
-"InstanceType": {
-"Description": "WebServer EC2 instance type",
-"Type": "String",
-"Default": "m1.small",
-"AllowedValues": [
-"m1.tiny",
-"m1.small",
-"m1.medium",
-"m1.large",
-"m1.xlarge"
-],
-"ConstraintDescription": "must be a valid EC2 instance type."
-},
-"DBName": {
-"Default": "wordpress",
-"Description": "The WordPress database name",
-"Type": "String",
-"MinLength": "1",
-"MaxLength": "64",
-"AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*",
-"ConstraintDescription": "must begin with a letter and..."
-},
-"DBUsername": {
-"Default": "admin",
-"NoEcho": "true",
-"Description": "The WordPress database admin account username",
-"Type": "String",
-"MinLength": "1",
-"MaxLength": "16",
-"AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*",
-"ConstraintDescription": "must begin with a letter and..."
-},
-"DBPassword": {
-"Default": "admin",
-"NoEcho": "true",
-"Description": "The WordPress database admin account password",
-"Type": "String",
-"MinLength": "1",
-"MaxLength": "41",
-"AllowedPattern": "[a-zA-Z0-9]*",
-"ConstraintDescription": "must contain only alphanumeric characters."
-},
-"DBRootPassword": {
-"Default": "admin",
-"NoEcho": "true",
-"Description": "Root password for MySQL",
-"Type": "String",
-"MinLength": "1",
-"MaxLength": "41",
-"AllowedPattern": "[a-zA-Z0-9]*",
-"ConstraintDescription": "must contain only alphanumeric characters."
-},
-"LinuxDistribution": {
-"Default": "F17",
-"Description": "Distribution of choice",
-"Type": "String",
-"AllowedValues": [
-"F18",
-"F17",
-"U10",
-"RHEL-6.1",
-"RHEL-6.2",
-"RHEL-6.3"
-]
-},
-"Network": {
-"Type": "String",
-"CustomConstraint": "neutron.network"
-}
-},
-"Mappings": {
-"AWSInstanceType2Arch": {
-"m1.tiny": {
-"Arch": "32"
-},
-"m1.small": {
-"Arch": "64"
-},
-"m1.medium": {
-"Arch": "64"
-},
-"m1.large": {
-"Arch": "64"
-},
-"m1.xlarge": {
-"Arch": "64"
-}
-},
-"DistroArch2AMI": {
-"F18": {
-"32": "F18-i386-cfntools",
-"64": "F18-x86_64-cfntools"
-},
-"F17": {
-"32": "F17-i386-cfntools",
-"64": "F17-x86_64-cfntools"
-},
-"U10": {
-"32": "U10-i386-cfntools",
-"64": "U10-x86_64-cfntools"
-},
-"RHEL-6.1": {
-"32": "rhel61-i386-cfntools",
-"64": "rhel61-x86_64-cfntools"
-},
-"RHEL-6.2": {
-"32": "rhel62-i386-cfntools",
-"64": "rhel62-x86_64-cfntools"
-},
-"RHEL-6.3": {
-"32": "rhel63-i386-cfntools",
-"64": "rhel63-x86_64-cfntools"
-}
-}
-},
-"Resources": {
-"WikiDatabase": {
-"Type": "AWS::EC2::Instance",
-"Metadata": {
-"AWS::CloudFormation::Init": {
-"config": {
-"packages": {
-"yum": {
-"mysql": [],
-"mysql-server": [],
-"httpd": [],
-"wordpress": []
-}
-},
-"services": {
-"systemd": {
-"mysqld": {
-"enabled": "true",
-"ensureRunning": "true"
-},
-"httpd": {
-"enabled": "true",
-"ensureRunning": "true"
-}
-}
-}
-}
-}
-},
-"Properties": {
-"ImageId": {
-"Fn::FindInMap": [
-"DistroArch2AMI",
-{
-"Ref": "LinuxDistribution"
-},
-{
-"Fn::FindInMap": [
-"AWSInstanceType2Arch",
-{
-"Ref": "InstanceType"
-},
-"Arch"
-]
-}
-]
-},
-"InstanceType": {
-"Ref": "InstanceType"
-},
-"KeyName": {
-"Ref": "KeyName"
-},
-"UserData": {
-"Fn::Base64": {
-"Fn::Join": [
-"",
-[
-"#!/bin/bash -v\\n",
-"/opt/aws/bin/cfn-init\\n"
-]
-]
-}
-}
-}
-}
-},
-"Outputs": {
-"WebsiteURL": {
-"Value": {
-"Fn::Join": [
-"",
-[
-"http://",
-{
-"Fn::GetAtt": [
-"WikiDatabase",
-"PublicIp"
-]
-},
-"/wordpress"
-]
-]
-},
-"Description": "URL for Wordpress wiki"
-}
-}
-}
-"""
-
-VALIDATE = """
-{
-"Description": "AWS CloudFormation Sample Template.",
-"Parameters": {
-"DBUsername": {
-"Type": "String",
-"Description": "The WordPress database admin account username",
-"Default": "admin",
-"MinLength": "1",
-"AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*",
-"NoEcho": "true",
-"MaxLength": "16",
-"ConstraintDescription": "must begin with a letter and..."
-},
-"LinuxDistribution": {
-"Default": "F17",
-"Type": "String",
-"Description": "Distribution of choice",
-"AllowedValues": [
-"F18",
-"F17",
-"U10",
-"RHEL-6.1",
-"RHEL-6.2",
-"RHEL-6.3"
-]
-},
-"DBRootPassword": {
-"Type": "String",
-"Description": "Root password for MySQL",
-"Default": "admin",
-"MinLength": "1",
-"AllowedPattern": "[a-zA-Z0-9]*",
-"NoEcho": "true",
-"MaxLength": "41",
-"ConstraintDescription": "must contain only alphanumeric characters."
-},
-"KeyName": {
-"Type": "String",
-"Description": "Name of an EC2 Key Pair to enable SSH access to the instances"
-},
-"DBName": {
-"Type": "String",
-"Description": "The WordPress database name",
-"Default": "wordpress",
-"MinLength": "1",
-"AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*",
-"MaxLength": "64",
-"ConstraintDescription": "must begin with a letter and..."
-},
-"DBPassword": {
-"Type": "String",
-"Description": "The WordPress database admin account password",
-"Default": "admin",
-"MinLength": "1",
-"AllowedPattern": "[a-zA-Z0-9]*",
-"NoEcho": "true",
-"MaxLength": "41",
-"ConstraintDescription": "must contain only alphanumeric characters."
-},
-"InstanceType": {
-"Default": "m1.small",
-"Type": "String",
-"ConstraintDescription": "must be a valid EC2 instance type.",
-"Description": "WebServer EC2 instance type",
-"AllowedValues": [
-"m1.tiny",
-"m1.small",
-"m1.medium",
-"m1.large",
-"m1.xlarge"
-]
-},
-"Network": {
-"Type": "String",
-"CustomConstraint": "neutron.network"
-}
-}
-}
-"""
-
-ENVIRONMENT = """
-parameters:
- InstanceType: m1.xsmall
- db_password: verybadpass
- KeyName: heat_key
-"""
-
-SNAPSHOT_CREATE = """
-{
- "status": "IN_PROGRESS",
- "name": "None",
- "data": "None",
- "creation_time": "2016-02-19T07:25:23.494152",
- "status_reason": "None",
- "id": "8af90c07-b788-44ee-a8ab-5990197f5e32"
-}
-"""
-
-
-class Environment(object):
- def __init__(self, data):
- self.data = data
-
-
-class Template(object):
- def __init__(self, data, validate):
- self.data = data
- self.validate = validate
-
-
-class Snapshot(object):
- def __init__(self, data):
- self.data = data
-
-
-def data(TEST):
- TEST.stacks = utils.TestDataContainer()
- TEST.stack_templates = utils.TestDataContainer()
- TEST.stack_environments = utils.TestDataContainer()
- TEST.stack_snapshot_create = utils.TestDataContainer()
- TEST.stack_snapshot = utils.TestDataContainer()
- TEST.resource_types = utils.TestDataContainer()
- TEST.heat_resources = utils.TestDataContainer()
- TEST.heat_services = utils.TestDataContainer()
- TEST.template_versions = utils.TestDataContainer()
- TEST.template_functions = utils.TestDataContainer()
-
- # Services
- service_1 = services.Service(services.ServiceManager(None), {
- "status": "up",
- "binary": "heat-engine",
- "report_interval": 60,
- "engine_id": "2f7b5a9b-c50b-4b01-8248-f89f5fb338d1",
- "created_at": "2015-02-06T03:23:32.000000",
- "hostname": "mrkanag",
- "updated_at": "2015-02-20T09:49:52.000000",
- "topic": "engine",
- "host": "engine-1",
- "deleted_at": None,
- "id": "1efd7015-5016-4caa-b5c8-12438af7b100"
- })
-
- service_2 = services.Service(services.ServiceManager(None), {
- "status": "up",
- "binary": "heat-engine",
- "report_interval": 60,
- "engine_id": "2f7b5a9b-c50b-4b01-8248-f89f5fb338d2",
- "created_at": "2015-02-06T03:23:32.000000",
- "hostname": "mrkanag",
- "updated_at": "2015-02-20T09:49:52.000000",
- "topic": "engine",
- "host": "engine-2",
- "deleted_at": None,
- "id": "1efd7015-5016-4caa-b5c8-12438af7b100"
- })
-
- TEST.heat_services.add(service_1)
- TEST.heat_services.add(service_2)
-
- # Data return by heatclient.
- TEST.api_resource_types = utils.TestDataContainer()
-
- for i in range(10):
- stack_data = {
- "description": "No description",
- "links": [{
- "href": "http://192.168.1.70:8004/v1/"
- "051c727ee67040d6a7b7812708485a97/"
- "stacks/stack-test{0}/"
- "05b4f39f-ea96-4d91-910c-e758c078a089{0}".format(i),
- "rel": "self"
- }],
- "parameters": {
- 'DBUsername': '******',
- 'InstanceType': 'm1.small',
- 'AWS::StackId': (
- 'arn:openstack:heat::2ce287:stacks/teststack/88553ec'),
- 'DBRootPassword': '******',
- 'AWS::StackName': "teststack{0}".format(i),
- 'DBPassword': '******',
- 'AWS::Region': 'ap-southeast-1',
- 'DBName': u'wordpress'
- },
- "stack_status_reason": "Stack successfully created",
- "stack_name": "stack-test{0}".format(i),
- "creation_time": "2013-04-22T00:11:39Z",
- "updated_time": "2013-04-22T00:11:39Z",
- "stack_status": "CREATE_COMPLETE",
- "id": "05b4f39f-ea96-4d91-910c-e758c078a089{0}".format(i)
- }
- stack = stacks.Stack(stacks.StackManager(None), stack_data)
- TEST.stacks.add(stack)
-
- for i in range(10):
- snapshot_data = {
- "status": "COMPLETE",
- "name": 'null',
- "data": {
- "files": {},
- "status": "COMPLETE",
- "name": "zhao3",
- "tags": ["a", " 123", " b", " 456"],
- "stack_user_project_id": "3cba4460875444049a2a7cc5420ccddb",
- "environment": {
- "encrypted_param_names": [],
- "parameter_defaults": {},
- "event_sinks": [],
- "parameters": {},
- "resource_registry": {
- "resources": {}
- }
- },
- "template": {
- "heat_template_version": "2013-05-23",
- "description":
- "HOT template for Test.",
- "resources": {
- "private_subnet": {
- "type": "OS::Neutron::Subnet",
- "properties": {
- "network_id": {"get_resource": "private_net"},
- "cidr": "172.16.2.0/24",
- "gateway_ip": "172.16.2.1"
- }
- },
- "private_net": {
- "type": "OS::Neutron::Net",
- "properties": {"name": "private-net"}
- }
- }
- },
- "action": "SNAPSHOT",
- "project_id": "1acd0026829f4d28bb2eff912d7aad0d",
- "id": "70650725-bdbd-419f-b53f-5707767bfe0e",
- "resources": {
- "private_subnet": {
- "status": "COMPLETE",
- "name": "private_subnet",
- "resource_data": {},
- "resource_id": "9c7211b3-31c7-41f6-b92a-442ad3f71ef0",
- "action": "SNAPSHOT",
- "type": "OS::Neutron::Subnet",
- "metadata": {}
- },
- "private_net": {
- "status": "COMPLETE",
- "name": "private_net",
- "resource_data": {},
- "resource_id": "ff4fd287-31b2-4d00-bc96-c409bc1db027",
- "action": "SNAPSHOT",
- "type": "OS::Neutron::Net",
- "metadata": {}
- }
- }
- },
-
- "creation_time": "2016-02-21T04:02:54",
- "status_reason": "Stack SNAPSHOT completed successfully",
- "id": "01558a3b-ba05-4427-bbb4-1e4ab71cfca{0}".format(i)
- }
- TEST.stack_snapshot.add(snapshot_data)
-
- TEST.stack_templates.add(Template(TEMPLATE, VALIDATE))
- TEST.stack_environments.add(Environment(ENVIRONMENT))
- TEST.stack_snapshot_create.add(Snapshot(SNAPSHOT_CREATE))
-
- # Resource types list
- r_type_1 = {
- "resource_type": "AWS::CloudFormation::Stack",
- "attributes": {},
- "properties": {
- "Parameters": {
- "description":
- "The set of parameters passed to this nested stack.",
- "immutable": False,
- "required": False,
- "type": "map",
- "update_allowed": True},
- "TemplateURL": {
- "description": "The URL of a template that specifies"
- " the stack to be created as a resource.",
- "immutable": False,
- "required": True,
- "type": "string",
- "update_allowed": True},
- "TimeoutInMinutes": {
- "description": "The length of time, in minutes,"
- " to wait for the nested stack creation.",
- "immutable": False,
- "required": False,
- "type": "number",
- "update_allowed": True}
- }
- }
-
- r_type_2 = {
- "resource_type": "OS::Heat::CloudConfig",
- "attributes": {
- "config": {
- "description": "The config value of the software config."}
- },
- "properties": {
- "cloud_config": {
- "description": "Map representing the cloud-config data"
- " structure which will be formatted as YAML.",
- "immutable": False,
- "required": False,
- "type": "map",
- "update_allowed": False}
- }
- }
-
- r_types_list = [r_type_1, r_type_2]
-
- for rt in r_types_list:
- r_type = resource_types.ResourceType(
- resource_types.ResourceTypeManager(None), rt['resource_type'])
- TEST.resource_types.add(r_type)
- TEST.api_resource_types.add(rt)
-
- # Resources
- resource_1 = resources.Resource(resources.ResourceManager(None), {
- "logical_resource_id": "my_resource",
- "physical_resource_id": "7b5e29b1-c94d-402d-b69c-df9ac6dfc0ce",
- "resource_name": "my_resource",
- "links": [
- {
- "href": "http://192.168.1.70:8004/v1/"
- "051c727ee67040d6a7b7812708485a97/"
- "stacks/%s/%s/resources/my_resource" %
- (TEST.stacks.first().stack_name,
- TEST.stacks.first().id),
- "rel": "self"
- },
- {
- "href": "http://192.168.1.70:8004/v1/"
- "051c727ee67040d6a7b7812708485a97/"
- "stacks/%s/%s" %
- (TEST.stacks.first().stack_name,
- TEST.stacks.first().id),
- "rel": "stack"
- }
- ],
- "attributes": {
- "metadata": {}
- }
- })
-
- TEST.heat_resources.add(resource_1)
-
- # Template versions
- template_version_1 = template_versions.TemplateVersion(
- template_versions.TemplateVersionManager(None), {
- "version": "HeatTemplateFormatVersion.2012-12-12",
- "type": "cfn"
- })
-
- template_version_2 = template_versions.TemplateVersion(
- template_versions.TemplateVersionManager(None), {
- "version": "heat_template_version.2013-05-23",
- "type": "hot"
- })
-
- TEST.template_versions.add(template_version_1)
- TEST.template_versions.add(template_version_2)
-
- # Template functions
- template_function_1 = template_versions.TemplateVersion(
- template_versions.TemplateVersionManager(None), {
- "functions": "Fn::GetAZs",
- "description": "A function for retrieving the availability zones."
- })
-
- template_function_2 = template_versions.TemplateVersion(
- template_versions.TemplateVersionManager(None), {
- "functions": "Fn::Join",
- "description": "A function for joining strings."
- })
-
- TEST.template_functions.add(template_function_1)
- TEST.template_functions.add(template_function_2)
diff --git a/openstack_dashboard/test/test_data/keystone_data.py b/openstack_dashboard/test/test_data/keystone_data.py
index 2a37f20996..a43d56565d 100644
--- a/openstack_dashboard/test/test_data/keystone_data.py
+++ b/openstack_dashboard/test/test_data/keystone_data.py
@@ -103,14 +103,6 @@ SERVICE_CATALOG = [
"adminURL": "http://admin.nova.example.com:8773/services/Admin",
"publicURL": "http://public.nova.example.com:8773/services/Cloud",
"internalURL": "http://int.nova.example.com:8773/services/Cloud"}]},
- {"type": "orchestration",
- "name": "Heat",
- "endpoints_links": [],
- "endpoints": [
- {"region": "RegionOne",
- "adminURL": "http://admin.heat.example.com:8004/v1",
- "publicURL": "http://public.heat.example.com:8004/v1",
- "internalURL": "http://int.heat.example.com:8004/v1"}]}
]
diff --git a/openstack_dashboard/test/test_data/utils.py b/openstack_dashboard/test/test_data/utils.py
index 4337bf0c0b..79c2f84f4b 100644
--- a/openstack_dashboard/test/test_data/utils.py
+++ b/openstack_dashboard/test/test_data/utils.py
@@ -17,7 +17,6 @@ def load_test_data(load_onto=None):
from openstack_dashboard.test.test_data import cinder_data
from openstack_dashboard.test.test_data import exceptions
from openstack_dashboard.test.test_data import glance_data
- from openstack_dashboard.test.test_data import heat_data
from openstack_dashboard.test.test_data import keystone_data
from openstack_dashboard.test.test_data import neutron_data
from openstack_dashboard.test.test_data import nova_data
@@ -32,7 +31,6 @@ def load_test_data(load_onto=None):
cinder_data.data,
neutron_data.data,
swift_data.data,
- heat_data.data,
)
if load_onto:
for data_func in loaders:
diff --git a/releasenotes/notes/heat-panel-splitout-b609b157aa4bf29b.yaml b/releasenotes/notes/heat-panel-splitout-b609b157aa4bf29b.yaml
new file mode 100644
index 0000000000..69a8ad3fc7
--- /dev/null
+++ b/releasenotes/notes/heat-panel-splitout-b609b157aa4bf29b.yaml
@@ -0,0 +1,11 @@
+---
+upgrade:
+ - |
+ Heat dashboard is now split out into a separate project
+ ``heat-dashboard``. All new features and maintenances are
+ provided from the new project from now on. The new project provides
+ all features available in Horizon in the past release.
+ To continue to use heat dashboard, install ``heat-dashboard``
+ and set up the horizon plugin configuration file in ``enabled`` directory.
+ For more information, see ``heat-dashboard`` documentation
+ https://docs.openstack.org/heat-dashboard/latest/.
diff --git a/requirements.txt b/requirements.txt
index f6c26ac45d..31cacf34b1 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -30,7 +30,6 @@ pymongo!=3.1,>=3.0.2 # Apache-2.0
pyScss!=1.3.5,>=1.3.4 # MIT License
python-cinderclient>=3.2.0 # Apache-2.0
python-glanceclient>=2.8.0 # Apache-2.0
-python-heatclient>=1.10.0 # Apache-2.0
python-keystoneclient>=3.8.0 # Apache-2.0
python-neutronclient>=6.3.0 # Apache-2.0
python-novaclient>=9.1.0 # Apache-2.0
diff --git a/tools/gate/integration/devstack_gate_rc b/tools/gate/integration/devstack_gate_rc
index 1579b49f69..83eab88d03 100644
--- a/tools/gate/integration/devstack_gate_rc
+++ b/tools/gate/integration/devstack_gate_rc
@@ -1,4 +1,4 @@
# This file contains various customized Devstack settings that Horizon uses at
# gate for integration tests job
-export ENABLED_SERVICES=heat,h-eng,h-api,h-api-cfn,h-api-cw
+